script/dom/subtlecrypto/
hkdf_operation.rs1use aws_lc_rs::hkdf;
6
7use crate::dom::bindings::codegen::Bindings::CryptoKeyBinding::{KeyType, KeyUsage};
8use crate::dom::bindings::codegen::Bindings::SubtleCryptoBinding::KeyFormat;
9use crate::dom::bindings::error::Error;
10use crate::dom::bindings::root::DomRoot;
11use crate::dom::cryptokey::{CryptoKey, Handle};
12use crate::dom::globalscope::GlobalScope;
13use crate::dom::subtlecrypto::{
14 ALG_HKDF, ALG_SHA1, ALG_SHA256, ALG_SHA384, ALG_SHA512, KeyAlgorithmAndDerivatives,
15 SubtleHkdfParams, SubtleKeyAlgorithm,
16};
17use crate::script_runtime::CanGc;
18
19pub(crate) fn derive_bits(
21 normalized_algorithm: &SubtleHkdfParams,
22 key: &CryptoKey,
23 length: Option<u32>,
24) -> Result<Vec<u8>, Error> {
25 let Some(length) = length else {
28 return Err(Error::Operation);
29 };
30 if length == 0 || length % 8 != 0 {
31 return Err(Error::Operation);
32 };
33
34 let key_derivation_key = key.handle().as_bytes();
36
37 let mut result = vec![0; length as usize / 8];
46 let algorithm = match normalized_algorithm.hash.name.as_str() {
47 ALG_SHA1 => hkdf::HKDF_SHA1_FOR_LEGACY_USE_ONLY,
48 ALG_SHA256 => hkdf::HKDF_SHA256,
49 ALG_SHA384 => hkdf::HKDF_SHA384,
50 ALG_SHA512 => hkdf::HKDF_SHA512,
51 _ => {
52 return Err(Error::NotSupported);
53 },
54 };
55 let salt = hkdf::Salt::new(algorithm, &normalized_algorithm.salt);
56 let info = normalized_algorithm.info.as_slice();
57 let pseudo_random_key = salt.extract(key_derivation_key);
58 let Ok(output_key_material) = pseudo_random_key.expand(std::slice::from_ref(&info), algorithm)
59 else {
60 return Err(Error::Operation);
61 };
62 if output_key_material.fill(&mut result).is_err() {
63 return Err(Error::Operation);
64 };
65
66 Ok(result)
68}
69
70pub(crate) fn import(
72 global: &GlobalScope,
73 format: KeyFormat,
74 key_data: &[u8],
75 extractable: bool,
76 usages: Vec<KeyUsage>,
77 can_gc: CanGc,
78) -> Result<DomRoot<CryptoKey>, Error> {
79 if format == KeyFormat::Raw {
83 if usages
86 .iter()
87 .any(|usage| !matches!(usage, KeyUsage::DeriveKey | KeyUsage::DeriveBits)) ||
88 usages.is_empty()
89 {
90 return Err(Error::Syntax(None));
91 }
92
93 if extractable {
95 return Err(Error::Syntax(None));
96 }
97
98 let algorithm = SubtleKeyAlgorithm {
104 name: ALG_HKDF.to_string(),
105 };
106 let key = CryptoKey::new(
107 global,
108 KeyType::Secret,
109 extractable,
110 KeyAlgorithmAndDerivatives::KeyAlgorithm(algorithm),
111 usages,
112 Handle::Hkdf(key_data.to_vec()),
113 can_gc,
114 );
115
116 Ok(key)
118 }
119 else {
121 Err(Error::NotSupported)
123 }
124}
125
126pub(crate) fn get_key_length() -> Result<Option<u32>, Error> {
128 Ok(None)
130}