blob: 2ba89b84c1ee0f91235b199f2fb6d1810abb4df2 [file]
// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
// SPDX-License-Identifier: Apache-2.0
use std::future::Future;
use rquickjs::{Array, Class, Ctx, FromJs, Result, Value};
use super::{
algorithm_not_supported_error,
crypto_key::{CryptoKey, KeyKind},
derive_algorithm::DeriveAlgorithm,
derive_bits::{derive_bits, DeriveBitsLength},
key_algorithm::{KeyAlgorithm, KeyAlgorithmMode, KeyAlgorithmWithUsages},
util::ResultDomExt,
};
pub fn subtle_derive_key<'js>(
ctx: Ctx<'js>,
algorithm: Value<'js>,
base_key: Class<'js, CryptoKey<'js>>,
derived_key_algorithm: Value<'js>,
extractable: bool,
key_usages: Array<'js>,
) -> impl Future<Output = Result<Class<'js, CryptoKey<'js>>>> + 'js {
let prepared = prepare_derive_key(&ctx, algorithm, derived_key_algorithm, key_usages);
async move {
let (algorithm, key_algorithm) = prepared?;
derive_key(&ctx, &algorithm, &base_key, extractable, key_algorithm)
}
}
fn prepare_derive_key<'js>(
ctx: &Ctx<'js>,
algorithm: Value<'js>,
derived_key_algorithm: Value<'js>,
key_usages: Array<'js>,
) -> Result<(DeriveAlgorithm, KeyAlgorithmWithUsages)> {
let algorithm = DeriveAlgorithm::from_js(ctx, algorithm)?;
let key_algorithm = KeyAlgorithm::from_js(
ctx,
KeyAlgorithmMode::Derive,
derived_key_algorithm,
key_usages,
)?;
Ok((algorithm, key_algorithm))
}
fn derive_key<'js>(
ctx: &Ctx<'js>,
algorithm: &DeriveAlgorithm,
base_key: &Class<'js, CryptoKey<'js>>,
extractable: bool,
key_algorithm: KeyAlgorithmWithUsages,
) -> Result<Class<'js, CryptoKey<'js>>> {
let length = match &key_algorithm.algorithm {
KeyAlgorithm::Aes { length, .. } => *length,
KeyAlgorithm::Hmac { length, .. } => *length,
KeyAlgorithm::Derive { .. } => 0,
_ => {
return algorithm_not_supported_error(ctx);
},
};
let base_key = base_key.borrow();
base_key.check_validity("deriveKey").or_throw_dom(ctx)?;
let bytes = derive_bits(
ctx,
algorithm,
&base_key,
DeriveBitsLength::Specified(length as u32),
)?;
let key = CryptoKey::new(
KeyKind::Secret,
key_algorithm.name,
extractable,
key_algorithm.algorithm,
key_algorithm.public_usages,
bytes,
);
Class::instance(ctx.clone(), key)
}