script/dom/subtlecrypto/
hkdf_operation.rs1use hkdf::Hkdf;
6use sha1::Sha1;
7use sha2::{Sha256, Sha384, Sha512};
8
9use crate::dom::bindings::codegen::Bindings::CryptoKeyBinding::{KeyType, KeyUsage};
10use crate::dom::bindings::codegen::Bindings::SubtleCryptoBinding::KeyFormat;
11use crate::dom::bindings::error::Error;
12use crate::dom::bindings::root::DomRoot;
13use crate::dom::cryptokey::{CryptoKey, Handle};
14use crate::dom::globalscope::GlobalScope;
15use crate::dom::subtlecrypto::{
16 ALG_HKDF, ALG_SHA1, ALG_SHA256, ALG_SHA384, ALG_SHA512, KeyAlgorithmAndDerivatives,
17 SubtleHkdfParams, SubtleKeyAlgorithm,
18};
19use crate::script_runtime::CanGc;
20
21pub(crate) fn derive_bits(
23 normalized_algorithm: &SubtleHkdfParams,
24 key: &CryptoKey,
25 length: Option<u32>,
26) -> Result<Vec<u8>, Error> {
27 let Some(length) = length else {
29 return Err(Error::Operation(None));
30 };
31 if length % 8 != 0 {
32 return Err(Error::Operation(None));
33 };
34
35 let Handle::HkdfSecret(key_derivation_key) = key.handle() else {
37 return Err(Error::Operation(None));
38 };
39
40 let mut result = vec![0u8; length as usize / 8];
49 match normalized_algorithm.hash.name.as_str() {
50 ALG_SHA1 => Hkdf::<Sha1>::new(Some(&normalized_algorithm.salt), key_derivation_key)
51 .expand(&normalized_algorithm.info, &mut result)
52 .map_err(|_| Error::Operation(None))?,
53 ALG_SHA256 => Hkdf::<Sha256>::new(Some(&normalized_algorithm.salt), key_derivation_key)
54 .expand(&normalized_algorithm.info, &mut result)
55 .map_err(|_| Error::Operation(None))?,
56 ALG_SHA384 => Hkdf::<Sha384>::new(Some(&normalized_algorithm.salt), key_derivation_key)
57 .expand(&normalized_algorithm.info, &mut result)
58 .map_err(|_| Error::Operation(None))?,
59 ALG_SHA512 => Hkdf::<Sha512>::new(Some(&normalized_algorithm.salt), key_derivation_key)
60 .expand(&normalized_algorithm.info, &mut result)
61 .map_err(|_| Error::Operation(None))?,
62 _ => return Err(Error::Operation(None)),
63 }
64
65 Ok(result)
67}
68
69pub(crate) fn import_key(
71 global: &GlobalScope,
72 format: KeyFormat,
73 key_data: &[u8],
74 extractable: bool,
75 usages: Vec<KeyUsage>,
76 can_gc: CanGc,
77) -> Result<DomRoot<CryptoKey>, Error> {
78 if matches!(format, KeyFormat::Raw | KeyFormat::Raw_secret) {
82 if usages
85 .iter()
86 .any(|usage| !matches!(usage, KeyUsage::DeriveKey | KeyUsage::DeriveBits)) ||
87 usages.is_empty()
88 {
89 return Err(Error::Syntax(None));
90 }
91
92 if extractable {
94 return Err(Error::Syntax(None));
95 }
96
97 let algorithm = SubtleKeyAlgorithm {
103 name: ALG_HKDF.to_string(),
104 };
105 let key = CryptoKey::new(
106 global,
107 KeyType::Secret,
108 extractable,
109 KeyAlgorithmAndDerivatives::KeyAlgorithm(algorithm),
110 usages,
111 Handle::HkdfSecret(key_data.to_vec()),
112 can_gc,
113 );
114
115 Ok(key)
117 }
118 else {
120 Err(Error::NotSupported(None))
122 }
123}
124
125pub(crate) fn get_key_length() -> Result<Option<u32>, Error> {
127 Ok(None)
129}