script/dom/subtlecrypto/
aes_common.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 pkcs8::rand_core::{OsRng, RngCore};
8
9use crate::dom::bindings::codegen::Bindings::CryptoKeyBinding::{
10    CryptoKeyMethods, KeyType, KeyUsage,
11};
12use crate::dom::bindings::codegen::Bindings::SubtleCryptoBinding::{JsonWebKey, KeyFormat};
13use crate::dom::bindings::error::Error;
14use crate::dom::bindings::root::DomRoot;
15use crate::dom::bindings::str::DOMString;
16use crate::dom::cryptokey::{CryptoKey, Handle};
17use crate::dom::globalscope::GlobalScope;
18use crate::dom::subtlecrypto::{
19    ExportedKey, JsonWebKeyExt, JwkStringField, KeyAlgorithmAndDerivatives,
20    SubtleAesDerivedKeyParams, SubtleAesKeyAlgorithm, SubtleAesKeyGenParams,
21};
22use crate::script_runtime::CanGc;
23
24#[expect(clippy::enum_variant_names)]
25pub(crate) enum AesAlgorithm {
26    AesCtr,
27    AesCbc,
28    AesGcm,
29    AesKw,
30    AesOcb,
31}
32
33/// <https://w3c.github.io/webcrypto/#aes-ctr-operations-generate-key>
34/// <https://w3c.github.io/webcrypto/#aes-cbc-operations-generate-key>
35/// <https://w3c.github.io/webcrypto/#aes-gcm-operations-generate-key>
36/// <https://w3c.github.io/webcrypto/#aes-kw-operations-generate-key>
37/// <https://wicg.github.io/webcrypto-modern-algos/#aes-ocb-operations-generate-key>
38pub(crate) fn generate_key(
39    aes_algorithm: AesAlgorithm,
40    global: &GlobalScope,
41    normalized_algorithm: &SubtleAesKeyGenParams,
42    extractable: bool,
43    usages: Vec<KeyUsage>,
44    can_gc: CanGc,
45) -> Result<DomRoot<CryptoKey>, Error> {
46    match aes_algorithm {
47        AesAlgorithm::AesCtr |
48        AesAlgorithm::AesCbc |
49        AesAlgorithm::AesGcm |
50        AesAlgorithm::AesOcb => {
51            // Step 1. If usages contains any entry which is not one of "encrypt", "decrypt",
52            // "wrapKey" or "unwrapKey", then throw a SyntaxError.
53            if usages.iter().any(|usage| {
54                !matches!(
55                    usage,
56                    KeyUsage::Encrypt | KeyUsage::Decrypt | KeyUsage::WrapKey | KeyUsage::UnwrapKey
57                )
58            }) {
59                return Err(Error::Syntax(Some(
60                    "Usages contains an entry which is not one of \"encrypt\", \"decrypt\", \
61                    \"wrapKey\" or \"unwrapKey\""
62                        .to_string(),
63                )));
64            }
65        },
66        AesAlgorithm::AesKw => {
67            // Step 1. If usages contains any entry which is not one of "wrapKey" or "unwrapKey",
68            // then throw a SyntaxError.
69            if usages
70                .iter()
71                .any(|usage| !matches!(usage, KeyUsage::WrapKey | KeyUsage::UnwrapKey))
72            {
73                return Err(Error::Syntax(Some(
74                    "Usages contains an entry which is not one of \"wrapKey\" or \"unwrapKey\""
75                        .to_string(),
76                )));
77            }
78        },
79    }
80
81    // Step 2. If the length member of normalizedAlgorithm is not equal to one of 128, 192 or 256,
82    // then throw an OperationError.
83    // Step 3. Generate an AES key of length equal to the length member of normalizedAlgorithm.
84    // Step 4. If the key generation step fails, then throw an OperationError.
85    let handle =
86        match normalized_algorithm.length {
87            128 => {
88                let mut key_bytes = vec![0; 16];
89                OsRng.fill_bytes(&mut key_bytes);
90                Handle::Aes128Key(Key::<Aes128>::clone_from_slice(&key_bytes))
91            },
92            192 => {
93                let mut key_bytes = vec![0; 24];
94                OsRng.fill_bytes(&mut key_bytes);
95                Handle::Aes192Key(Key::<Aes192>::clone_from_slice(&key_bytes))
96            },
97            256 => {
98                let mut key_bytes = vec![0; 32];
99                OsRng.fill_bytes(&mut key_bytes);
100                Handle::Aes256Key(Key::<Aes256>::clone_from_slice(&key_bytes))
101            },
102            _ => return Err(Error::Operation(Some(
103                "The length member of normalizedAlgorithm is not equal to one of 128, 192 or 256"
104                    .to_string(),
105            ))),
106        };
107
108    // Step 5. Let key be a new CryptoKey object representing the generated AES key.
109    // Step 6. Set the [[type]] internal slot of key to "secret".
110    // Step 7. Let algorithm be a new AesKeyAlgorithm.
111    // Step 9. Set the length attribute of algorithm to equal the length member of
112    // normalizedAlgorithm.
113    // Step 10. Set the [[algorithm]] internal slot of key to algorithm.
114    // Step 11. Set the [[extractable]] internal slot of key to be extractable.
115    // Step 12. Set the [[usages]] internal slot of key to be usages.
116    let algorithm_name = match aes_algorithm {
117        AesAlgorithm::AesCtr => {
118            // Step 8. Set the name attribute of algorithm to "AES-CTR".
119            "AES-CTR"
120        },
121        AesAlgorithm::AesCbc => {
122            // Step 8. Set the name attribute of algorithm to "AES-CBC".
123            "AES-CBC"
124        },
125        AesAlgorithm::AesGcm => {
126            // Step 8. Set the name attribute of algorithm to "AES-GCM".
127            "AES-GCM"
128        },
129        AesAlgorithm::AesKw => {
130            // Step 8. Set the name attribute of algorithm to "AES-KW".
131            "AES-KW"
132        },
133        AesAlgorithm::AesOcb => {
134            // Step 8. Set the name attribute of algorithm to "AES-OCB".
135            "AES-OCB"
136        },
137    };
138    let algorithm = SubtleAesKeyAlgorithm {
139        name: algorithm_name.to_string(),
140        length: normalized_algorithm.length,
141    };
142    let key = CryptoKey::new(
143        global,
144        KeyType::Secret,
145        extractable,
146        KeyAlgorithmAndDerivatives::AesKeyAlgorithm(algorithm),
147        usages,
148        handle,
149        can_gc,
150    );
151
152    // Step 13. Return key.
153    Ok(key)
154}
155
156/// Step 3 of <https://w3c.github.io/webcrypto/#aes-ctr-operations-import-key>
157/// Step 3 of <https://w3c.github.io/webcrypto/#aes-cbc-operations-import-key>
158/// Step 3 of <https://w3c.github.io/webcrypto/#aes-gcm-operations-import-key>
159/// Step 3 of <https://w3c.github.io/webcrypto/#aes-kw-operations-import-key>
160/// Step 3 of <https://wicg.github.io/webcrypto-modern-algos/#aes-ocb-operations-import-key>
161pub(crate) fn import_key_from_key_data(
162    aes_algorithm: AesAlgorithm,
163    format: KeyFormat,
164    key_data: &[u8],
165    extractable: bool,
166    usages: &[KeyUsage],
167) -> Result<Vec<u8>, Error> {
168    let data;
169    match format {
170        // If format is "raw": (Only applied to AES-CTR, AES-CBC, AES-GCM, AES-KW)
171        KeyFormat::Raw
172            if matches!(
173                aes_algorithm,
174                AesAlgorithm::AesCtr |
175                    AesAlgorithm::AesCbc |
176                    AesAlgorithm::AesGcm |
177                    AesAlgorithm::AesKw
178            ) =>
179        {
180            // Step 1. Let data be keyData.
181            data = key_data.to_vec();
182
183            // Step 2. If the length in bits of data is not 128, 192 or 256 then throw a DataError.
184            if !matches!(data.len(), 16 | 24 | 32) {
185                return Err(Error::Data(Some(
186                    "The length in bits of data is not 128, 192 or 256".to_string(),
187                )));
188            }
189        },
190        // If format is "raw-secret":
191        KeyFormat::Raw_secret => {
192            // Step 1. Let data be keyData.
193            data = key_data.to_vec();
194
195            // Step 2. If the length in bits of data is not 128, 192 or 256 then throw a DataError.
196            if !matches!(data.len(), 16 | 24 | 32) {
197                return Err(Error::Data(Some(
198                    "The length in bits of key is not 128, 192 or 256".to_string(),
199                )));
200            }
201        },
202        // If format is "jwk":
203        KeyFormat::Jwk => {
204            // Step 1.
205            // If keyData is a JsonWebKey dictionary:
206            //     Let jwk equal keyData.
207            // Otherwise:
208            //     Throw a DataError.
209            let jwk = JsonWebKey::parse(GlobalScope::get_cx(), key_data)?;
210
211            // Step 3.2. If the kty field of jwk is not "oct", then throw a DataError.
212            if jwk.kty.as_ref().is_none_or(|kty| kty != "oct") {
213                return Err(Error::Data(Some(
214                    "The kty field of jwk is not \"oct\"".to_string(),
215                )));
216            }
217
218            // Step 3. If jwk does not meet the requirements of Section 6.4 of JSON Web Algorithms
219            // [JWA], then throw a DataError.
220            // Step 4. Let data be the byte sequence obtained by decoding the k field of jwk.
221            data = jwk.decode_required_string_field(JwkStringField::K)?;
222
223            match aes_algorithm {
224                AesAlgorithm::AesCtr => {
225                    // Step 5.
226                    // If data has length 128 bits:
227                    //     If the alg field of jwk is present, and is not "A128CTR", then throw a
228                    //     DataError.
229                    // If data has length 192 bits:
230                    //     If the alg field of jwk is present, and is not "A192CTR", then throw a
231                    //     DataError.
232                    // If data has length 256 bits:
233                    //     If the alg field of jwk is present, and is not "A256CTR", then throw a
234                    //     DataError.
235                    // Otherwise:
236                    //     throw a DataError.
237                    let expected_alg = match data.len() {
238                        16 => "A128CTR",
239                        24 => "A192CTR",
240                        32 => "A256CTR",
241                        _ => {
242                            return Err(Error::Data(Some(
243                                "The length in bits of data is not 128, 192 or 256".to_string(),
244                            )));
245                        },
246                    };
247                    if jwk.alg.as_ref().is_none_or(|alg| alg != expected_alg) {
248                        return Err(Error::Data(Some(format!(
249                            "The alg field of jwk is present, and is not {}",
250                            expected_alg
251                        ))));
252                    }
253                },
254                AesAlgorithm::AesCbc => {
255                    // Step 5.
256                    // If data has length 128 bits:
257                    //     If the alg field of jwk is present, and is not "A128CBC", then throw a
258                    //     DataError.
259                    // If data has length 192 bits:
260                    //     If the alg field of jwk is present, and is not "A192CBC", then throw a
261                    //     DataError.
262                    // If data has length 256 bits:
263                    //     If the alg field of jwk is present, and is not "A256CBC", then throw a
264                    //     DataError.
265                    // Otherwise:
266                    //     throw a DataError.
267                    let expected_alg = match data.len() {
268                        16 => "A128CBC",
269                        24 => "A192CBC",
270                        32 => "A256CBC",
271                        _ => {
272                            return Err(Error::Data(Some(
273                                "The length in bits of data is not 128, 192 or 256".to_string(),
274                            )));
275                        },
276                    };
277                    if jwk.alg.as_ref().is_none_or(|alg| alg != expected_alg) {
278                        return Err(Error::Data(Some(format!(
279                            "The alg field of jwk is present, and is not {}",
280                            expected_alg
281                        ))));
282                    }
283                },
284                AesAlgorithm::AesGcm => {
285                    // Step 5.
286                    // If data has length 128 bits:
287                    //     If the alg field of jwk is present, and is not "A128GCM", then throw a
288                    //     DataError.
289                    // If data has length 192 bits:
290                    //     If the alg field of jwk is present, and is not "A192GCM", then throw a
291                    //     DataError.
292                    // If data has length 256 bits:
293                    //     If the alg field of jwk is present, and is not "A256GCM", then throw a
294                    //     DataError.
295                    // Otherwise:
296                    //     throw a DataError.
297                    let expected_alg = match data.len() {
298                        16 => "A128GCM",
299                        24 => "A192GCM",
300                        32 => "A256GCM",
301                        _ => {
302                            return Err(Error::Data(Some(
303                                "The length in bits of data is not 128, 192 or 256".to_string(),
304                            )));
305                        },
306                    };
307                    if jwk.alg.as_ref().is_none_or(|alg| alg != expected_alg) {
308                        return Err(Error::Data(Some(format!(
309                            "The alg field of jwk is present, and is not {}",
310                            expected_alg
311                        ))));
312                    }
313                },
314                AesAlgorithm::AesKw => {
315                    // Step 5.
316                    // If data has length 128 bits:
317                    //     If the alg field of jwk is present, and is not "A128KW", then throw a
318                    //     DataError.
319                    // If data has length 192 bits:
320                    //     If the alg field of jwk is present, and is not "A192KW", then throw a
321                    //     DataError.
322                    // If data has length 256 bits:
323                    //     If the alg field of jwk is present, and is not "A256KW", then throw a
324                    //     DataError.
325                    // Otherwise:
326                    //     throw a DataError.
327                    let expected_alg = match data.len() {
328                        16 => "A128KW",
329                        24 => "A192KW",
330                        32 => "A256KW",
331                        _ => {
332                            return Err(Error::Data(Some(
333                                "The length in bits of data is not 128, 192 or 256".to_string(),
334                            )));
335                        },
336                    };
337                    if jwk.alg.as_ref().is_none_or(|alg| alg != expected_alg) {
338                        return Err(Error::Data(Some(format!(
339                            "The alg field of jwk is present, and is not {}",
340                            expected_alg
341                        ))));
342                    }
343                },
344                AesAlgorithm::AesOcb => {
345                    // Step 5.
346                    // If data has length 128 bits:
347                    //     If the alg field of jwk is present, and is not "A128OCB", then throw a
348                    //     DataError.
349                    // If data has length 192 bits:
350                    //     If the alg field of jwk is present, and is not "A192OCB", then throw a
351                    //     DataError.
352                    // If data has length 256 bits:
353                    //     If the alg field of jwk is present, and is not "A256OCB", then throw a
354                    //     DataError.
355                    // Otherwise:
356                    //     throw a DataError.
357                    let expected_alg = match data.len() {
358                        16 => "A128OCB",
359                        24 => "A192OCB",
360                        32 => "A256OCB",
361                        _ => {
362                            return Err(Error::Data(Some(
363                                "The length in bits of key is not 128, 192 or 256".to_string(),
364                            )));
365                        },
366                    };
367                    if jwk.alg.as_ref().is_none_or(|alg| alg != expected_alg) {
368                        return Err(Error::Data(Some(format!(
369                            "The alg field of jwk is present, and is not {}",
370                            expected_alg
371                        ))));
372                    }
373                },
374            }
375
376            // Step 6. If usages is non-empty and the use field of jwk is present and is not "enc",
377            // then throw a DataError.
378            if !usages.is_empty() && jwk.use_.as_ref().is_some_and(|use_| use_ != "enc") {
379                return Err(Error::Data(Some(
380                    "Usages is non-empty and the use field of jwk is present and is not \"enc\""
381                        .to_string(),
382                )));
383            }
384
385            // Step 7. If the key_ops field of jwk is present, and is invalid according to the
386            // requirements of JSON Web Key [JWK] or does not contain all of the specified usages
387            // values, then throw a DataError.
388            jwk.check_key_ops(usages)?;
389
390            // Step 8. If the ext field of jwk is present and has the value false and extractable
391            // is true, then throw a DataError.
392            if jwk.ext.is_some_and(|ext| !ext) && extractable {
393                return Err(Error::Data(Some(
394                    "The ext field of jwk is present and has the value false and \
395                    extractable is true"
396                        .to_string(),
397                )));
398            }
399        },
400        // Otherwise:
401        _ => {
402            // throw a NotSupportedError.
403            return Err(Error::NotSupported(Some(
404                "Unupported import key format for AES key".to_string(),
405            )));
406        },
407    }
408
409    Ok(data)
410}
411
412/// <https://w3c.github.io/webcrypto/#aes-ctr-operations-export-key>
413/// <https://w3c.github.io/webcrypto/#aes-cbc-operations-export-key>
414/// <https://w3c.github.io/webcrypto/#aes-gcm-operations-export-key>
415/// <https://w3c.github.io/webcrypto/#aes-kw-operations-export-key>
416/// <https://wicg.github.io/webcrypto-modern-algos/#aes-ocb-operations-export-key>
417pub(crate) fn export_key(
418    aes_algorithm: AesAlgorithm,
419    format: KeyFormat,
420    key: &CryptoKey,
421) -> Result<ExportedKey, Error> {
422    // Step 1. If the underlying cryptographic key material represented by the [[handle]] internal
423    // slot of key cannot be accessed, then throw an OperationError.
424
425    // Step 2.
426    let result = match format {
427        // If format is "raw": (Only applied to AES-CTR, AES-CBC, AES-GCM, AES-KW)
428        KeyFormat::Raw
429            if matches!(
430                aes_algorithm,
431                AesAlgorithm::AesCtr |
432                    AesAlgorithm::AesCbc |
433                    AesAlgorithm::AesGcm |
434                    AesAlgorithm::AesKw
435            ) =>
436        {
437            // Step 2.1. Let data be a byte sequence containing the raw octets of the key
438            // represented by [[handle]] internal slot of key.
439            let data = match key.handle() {
440                Handle::Aes128Key(key) => key.to_vec(),
441                Handle::Aes192Key(key) => key.to_vec(),
442                Handle::Aes256Key(key) => key.to_vec(),
443                _ => {
444                    return Err(Error::Operation(Some(
445                        "The key handle is not representing an AES key".to_string(),
446                    )));
447                },
448            };
449
450            // Step 2.2. Let result be data.
451            ExportedKey::Bytes(data)
452        },
453        // If format is "raw-secret":
454        KeyFormat::Raw_secret => {
455            // Step 2.1. Let data be a byte sequence containing the raw octets of the key
456            // represented by [[handle]] internal slot of key.
457            let data = match key.handle() {
458                Handle::Aes128Key(key) => key.to_vec(),
459                Handle::Aes192Key(key) => key.to_vec(),
460                Handle::Aes256Key(key) => key.to_vec(),
461                _ => {
462                    return Err(Error::Operation(Some(
463                        "The key handle is not representing an AES key".to_string(),
464                    )));
465                },
466            };
467
468            // Step 2.2. Let result be data.
469            ExportedKey::Bytes(data)
470        },
471        // If format is "jwk":
472        KeyFormat::Jwk => {
473            // Step 2.1. Let jwk be a new JsonWebKey dictionary.
474            // Step 2.2. Set the kty attribute of jwk to the string "oct".
475            let mut jwk = JsonWebKey {
476                kty: Some(DOMString::from("oct")),
477                ..Default::default()
478            };
479
480            // Step 2.3. Set the k attribute of jwk to be a string containing the raw octets of the
481            // key represented by [[handle]] internal slot of key, encoded according to Section 6.4
482            // of JSON Web Algorithms [JWA].
483            let key_bytes = match key.handle() {
484                Handle::Aes128Key(key) => key.as_slice(),
485                Handle::Aes192Key(key) => key.as_slice(),
486                Handle::Aes256Key(key) => key.as_slice(),
487                _ => {
488                    return Err(Error::Operation(Some(
489                        "The key handle is not representing an AES key".to_string(),
490                    )));
491                },
492            };
493            jwk.encode_string_field(JwkStringField::K, key_bytes);
494
495            match aes_algorithm {
496                AesAlgorithm::AesCtr => {
497                    // Step 2.4.
498                    // If the length attribute of key is 128:
499                    //     Set the alg attribute of jwk to the string "A128CTR".
500                    // If the length attribute of key is 192:
501                    //     Set the alg attribute of jwk to the string "A192CTR".
502                    // If the length attribute of key is 256:
503                    //     Set the alg attribute of jwk to the string "A256CTR".
504                    let KeyAlgorithmAndDerivatives::AesKeyAlgorithm(algorithm) = key.algorithm()
505                    else {
506                        return Err(Error::Operation(None));
507                    };
508                    let alg = match algorithm.length {
509                        128 => "A128CTR",
510                        192 => "A192CTR",
511                        256 => "A256CTR",
512                        _ => return Err(Error::Operation(Some(
513                            "The length attribute of the [[algorithm]] internal slot of key is not \
514                            128, 192 or 256".to_string(),
515                        )))
516                    };
517                    jwk.alg = Some(DOMString::from(alg));
518                },
519                AesAlgorithm::AesCbc => {
520                    // Step 2.4.
521                    // If the length attribute of key is 128:
522                    //     Set the alg attribute of jwk to the string "A128CBC".
523                    // If the length attribute of key is 192:
524                    //     Set the alg attribute of jwk to the string "A192CBC".
525                    // If the length attribute of key is 256:
526                    //     Set the alg attribute of jwk to the string "A256CBC".
527                    let KeyAlgorithmAndDerivatives::AesKeyAlgorithm(algorithm) = key.algorithm()
528                    else {
529                        return Err(Error::Operation(None));
530                    };
531                    let alg = match algorithm.length {
532                        128 => "A128CBC",
533                        192 => "A192CBC",
534                        256 => "A256CBC",
535                        _ => return Err(Error::Operation(Some(
536                            "The length attribute of the [[algorithm]] internal slot of key is not \
537                            128, 192 or 256".to_string(),
538                        )))
539                    };
540                    jwk.alg = Some(DOMString::from(alg));
541                },
542                AesAlgorithm::AesGcm => {
543                    // Step 2.4.
544                    // If the length attribute of key is 128:
545                    //     Set the alg attribute of jwk to the string "A128GCM".
546                    // If the length attribute of key is 192:
547                    //     Set the alg attribute of jwk to the string "A192GCM".
548                    // If the length attribute of key is 256:
549                    //     Set the alg attribute of jwk to the string "A256GCM".
550                    let KeyAlgorithmAndDerivatives::AesKeyAlgorithm(algorithm) = key.algorithm()
551                    else {
552                        return Err(Error::Operation(None));
553                    };
554                    let alg = match algorithm.length {
555                        128 => "A128GCM",
556                        192 => "A192GCM",
557                        256 => "A256GCM",
558                        _ => return Err(Error::Operation(Some(
559                            "The length attribute of the [[algorithm]] internal slot of key is not \
560                            128, 192 or 256".to_string(),
561                        )))
562                    };
563                    jwk.alg = Some(DOMString::from(alg));
564                },
565                AesAlgorithm::AesKw => {
566                    // Step 2.4.
567                    // If the length attribute of key is 128:
568                    //     Set the alg attribute of jwk to the string "A128KW".
569                    // If the length attribute of key is 192:
570                    //     Set the alg attribute of jwk to the string "A192KW".
571                    // If the length attribute of key is 256:
572                    //     Set the alg attribute of jwk to the string "A256KW".
573                    let KeyAlgorithmAndDerivatives::AesKeyAlgorithm(algorithm) = key.algorithm()
574                    else {
575                        return Err(Error::Operation(None));
576                    };
577                    let alg = match algorithm.length {
578                        128 => "A128KW",
579                        192 => "A192KW",
580                        256 => "A256KW",
581                        _ => return Err(Error::Operation(Some(
582                            "The length attribute of the [[algorithm]] internal slot of key is not \
583                            128, 192 or 256".to_string(),
584                        )))
585                    };
586                    jwk.alg = Some(DOMString::from(alg));
587                },
588                AesAlgorithm::AesOcb => {
589                    // Step 2.4.
590                    // If the length attribute of key is 128:
591                    //     Set the alg attribute of jwk to the string "A128OCB".
592                    // If the length attribute of key is 192:
593                    //     Set the alg attribute of jwk to the string "A192OCB".
594                    // If the length attribute of key is 256:
595                    //     Set the alg attribute of jwk to the string "A256OCB".
596                    let KeyAlgorithmAndDerivatives::AesKeyAlgorithm(algorithm) = key.algorithm()
597                    else {
598                        return Err(Error::Operation(None));
599                    };
600                    let alg = match algorithm.length {
601                        128 => "A128OCB",
602                        192 => "A192OCB",
603                        256 => "A256OCB",
604                        _ => return Err(Error::Operation(Some(
605                            "The length attribute of the [[algorithm]] internal slot of key is not \
606                            128, 192 or 256".to_string(),
607                        )))
608                    };
609                    jwk.alg = Some(DOMString::from(alg));
610                },
611            }
612
613            // Step 2.5. Set the key_ops attribute of jwk to equal the usages attribute of key.
614            jwk.set_key_ops(key.usages());
615
616            // Step 2.6. Set the ext attribute of jwk to equal the [[extractable]] internal slot of
617            // key.
618            jwk.ext = Some(key.Extractable());
619
620            // Step 2.7. Let result be jwk.
621            ExportedKey::Jwk(Box::new(jwk))
622        },
623        _ => {
624            // throw a NotSupportedError.
625            return Err(Error::NotSupported(Some(
626                "Unsupported import key format for AES key".to_string(),
627            )));
628        },
629    };
630
631    // Step 3. Return result.
632    Ok(result)
633}
634
635/// <https://w3c.github.io/webcrypto/#aes-ctr-operations-get-key-length>
636/// <https://w3c.github.io/webcrypto/#aes-cbc-operations-get-key-length>
637/// <https://w3c.github.io/webcrypto/#aes-gcm-operations-get-key-length>
638/// <https://w3c.github.io/webcrypto/#aes-kw-operations-get-key-length>
639/// <https://wicg.github.io/webcrypto-modern-algos/#aes-ocb-operations-get-key-length>
640pub(crate) fn get_key_length(
641    normalized_derived_key_algorithm: &SubtleAesDerivedKeyParams,
642) -> Result<Option<u32>, Error> {
643    // Step 1. If the length member of normalizedDerivedKeyAlgorithm is not 128, 192 or 256, then
644    // throw an OperationError.
645    if !matches!(normalized_derived_key_algorithm.length, 128 | 192 | 256) {
646        return Err(Error::Operation(Some(
647            "The length member of normalizedDerivedKeyAlgorithm is not 128, 192 or 256".to_string(),
648        )));
649    }
650
651    // Step 2. Return the length member of normalizedDerivedKeyAlgorithm.
652    Ok(Some(normalized_derived_key_algorithm.length as u32))
653}