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(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 Handle::HkdfSecret(key_derivation_key) = key.handle() else {
39 return Err(Error::Operation(Some(
40 "The [[handle]] internal slot is not from an HKDF key".into(),
41 )));
42 };
43
44 let mut result = vec![0u8; length as usize / 8];
53 match normalized_algorithm.hash.name() {
54 ALG_SHA1 => Hkdf::<Sha1>::new(Some(&normalized_algorithm.salt), key_derivation_key)
55 .expand(&normalized_algorithm.info, &mut result)
56 .map_err(|error| Error::Operation(Some(error.to_string())))?,
57 ALG_SHA256 => Hkdf::<Sha256>::new(Some(&normalized_algorithm.salt), key_derivation_key)
58 .expand(&normalized_algorithm.info, &mut result)
59 .map_err(|error| Error::Operation(Some(error.to_string())))?,
60 ALG_SHA384 => Hkdf::<Sha384>::new(Some(&normalized_algorithm.salt), key_derivation_key)
61 .expand(&normalized_algorithm.info, &mut result)
62 .map_err(|error| Error::Operation(Some(error.to_string())))?,
63 ALG_SHA512 => Hkdf::<Sha512>::new(Some(&normalized_algorithm.salt), key_derivation_key)
64 .expand(&normalized_algorithm.info, &mut result)
65 .map_err(|error| Error::Operation(Some(error.to_string())))?,
66 algorithm_name => {
67 return Err(Error::Operation(Some(format!(
68 "Invalid hash algorithm: {algorithm_name}"
69 ))));
70 },
71 }
72
73 Ok(result)
75}
76
77pub(crate) fn import_key(
79 global: &GlobalScope,
80 format: KeyFormat,
81 key_data: &[u8],
82 extractable: bool,
83 usages: Vec<KeyUsage>,
84 can_gc: CanGc,
85) -> Result<DomRoot<CryptoKey>, Error> {
86 if matches!(format, KeyFormat::Raw | KeyFormat::Raw_secret) {
90 if usages
93 .iter()
94 .any(|usage| !matches!(usage, KeyUsage::DeriveKey | KeyUsage::DeriveBits)) ||
95 usages.is_empty()
96 {
97 return Err(Error::Syntax(Some(
98 "Usages contains an entry which is not \"deriveKey\" or \"deriveBits\"".into(),
99 )));
100 }
101
102 if extractable {
104 return Err(Error::Syntax(Some("'extractable' is not false".into())));
105 }
106
107 let algorithm = SubtleKeyAlgorithm {
113 name: ALG_HKDF.to_string(),
114 };
115 let key = CryptoKey::new(
116 global,
117 KeyType::Secret,
118 extractable,
119 KeyAlgorithmAndDerivatives::KeyAlgorithm(algorithm),
120 usages,
121 Handle::HkdfSecret(key_data.to_vec()),
122 can_gc,
123 );
124
125 Ok(key)
127 }
128 else {
130 Err(Error::NotSupported(Some(
132 "Formats different than \"raw\" are unsupported".into(),
133 )))
134 }
135}
136
137pub(crate) fn get_key_length() -> Result<Option<u32>, Error> {
139 Ok(None)
141}