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