script/dom/webcrypto/subtlecrypto/
pbkdf2_operation.rs1use std::num::NonZero;
6
7use aws_lc_rs::pbkdf2;
8use js::context::JSContext;
9
10use crate::dom::bindings::codegen::Bindings::CryptoKeyBinding::{KeyType, KeyUsage};
11use crate::dom::bindings::codegen::Bindings::SubtleCryptoBinding::KeyFormat;
12use crate::dom::bindings::error::Error;
13use crate::dom::bindings::root::DomRoot;
14use crate::dom::cryptokey::{CryptoKey, Handle, KeyUsageVecHelper};
15use crate::dom::globalscope::GlobalScope;
16use crate::dom::subtlecrypto::{
17 CryptoAlgorithm, KeyAlgorithmAndDerivatives, NormalizedAlgorithm, SubtleKeyAlgorithm,
18 SubtlePbkdf2Params,
19};
20
21pub(crate) fn derive_bits(
23 normalized_algorithm: &SubtlePbkdf2Params,
24 key: &CryptoKey,
25 length: Option<u32>,
26) -> Result<Vec<u8>, Error> {
27 let Some(length) = length else {
29 return Err(Error::Operation(Some("Length is null".into())));
30 };
31 if length % 8 != 0 {
32 return Err(Error::Operation(Some(
33 "Length is not a multiple of 8".into(),
34 )));
35 };
36
37 let Ok(iterations) = NonZero::<u32>::try_from(normalized_algorithm.iterations) else {
39 return Err(Error::Operation(Some(
40 "Normalized algorithm's iterations is zero".into(),
41 )));
42 };
43
44 if length == 0 {
46 return Ok(Vec::new());
47 }
48
49 let prf = match normalized_algorithm.hash.name() {
52 CryptoAlgorithm::Sha1 => pbkdf2::PBKDF2_HMAC_SHA1,
53 CryptoAlgorithm::Sha256 => pbkdf2::PBKDF2_HMAC_SHA256,
54 CryptoAlgorithm::Sha384 => pbkdf2::PBKDF2_HMAC_SHA384,
55 CryptoAlgorithm::Sha512 => pbkdf2::PBKDF2_HMAC_SHA512,
56 _ => {
57 return Err(Error::NotSupported(Some(
58 "Normalized algorithm's hash name is not supported".into(),
59 )));
60 },
61 };
62
63 let mut result = vec![0; length as usize / 8];
70 pbkdf2::derive(
71 prf,
72 iterations,
73 &normalized_algorithm.salt,
74 key.handle().as_bytes(),
75 &mut result,
76 );
77
78 Ok(result)
84}
85
86pub(crate) fn import_key(
88 cx: &mut JSContext,
89 global: &GlobalScope,
90 format: KeyFormat,
91 key_data: &[u8],
92 extractable: bool,
93 usages: Vec<KeyUsage>,
94) -> Result<DomRoot<CryptoKey>, Error> {
95 if !matches!(format, KeyFormat::Raw | KeyFormat::Raw_secret) {
97 return Err(Error::NotSupported(Some("Format is not raw".into())));
98 }
99
100 if usages
102 .iter()
103 .any(|usage| !matches!(usage, KeyUsage::DeriveKey | KeyUsage::DeriveBits)) ||
104 usages.is_empty()
105 {
106 return Err(Error::Syntax(Some(
107 "Usages is empty or contains a value that is not a 'deriveKey' or 'deriveBits'".into(),
108 )));
109 }
110
111 if extractable {
113 return Err(Error::Syntax(Some("Extractable is not false".into())));
114 }
115
116 let algorithm = SubtleKeyAlgorithm {
122 name: CryptoAlgorithm::Pbkdf2,
123 };
124 let key = CryptoKey::new(
125 cx,
126 global,
127 KeyType::Secret,
128 extractable,
129 KeyAlgorithmAndDerivatives::KeyAlgorithm(algorithm),
130 usages.normalized_value(),
131 Handle::Pbkdf2(key_data.to_vec().into()),
132 );
133
134 Ok(key)
136}
137
138pub(crate) fn get_key_length() -> Result<Option<u32>, Error> {
140 Ok(None)
142}