use crypto_core::{CryptoError, KeyWrapAlgorithm, KeyWrapFailureKind};
use super::{BackendErrorReason, OperationError, PrimitiveErrorReason};
use crate::secret_material::{bind_operation_policy, SecretMaterialOperation};
pub fn wrap_key(
algorithm: KeyWrapAlgorithm,
kek: &[u8],
key_data: &[u8],
) -> Result<crypto_aes_kw::AesKwWrappedKey, OperationError> {
let _policy = bind_operation_policy(SecretMaterialOperation::KeyWrap);
match algorithm {
KeyWrapAlgorithm::Aes128Kw => {
let kek = crypto_aes_kw::Aes128KwKek::from_slice(kek).map_err(map_key_wrap_error)?;
crypto_aes_kw::wrap_key_aes128(&kek, key_data).map_err(map_key_wrap_error)
}
KeyWrapAlgorithm::Aes192Kw => {
let kek = crypto_aes_kw::Aes192KwKek::from_slice(kek).map_err(map_key_wrap_error)?;
crypto_aes_kw::wrap_key_aes192(&kek, key_data).map_err(map_key_wrap_error)
}
KeyWrapAlgorithm::Aes256Kw => {
let kek = crypto_aes_kw::Aes256KwKek::from_slice(kek).map_err(map_key_wrap_error)?;
crypto_aes_kw::wrap_key_aes256(&kek, key_data).map_err(map_key_wrap_error)
}
_ => Err(OperationError::Provider {
reason: super::ProviderErrorReason::UnsupportedAlgorithm,
}),
}
}
pub fn unwrap_key(
algorithm: KeyWrapAlgorithm,
kek: &[u8],
wrapped_key: &[u8],
) -> Result<crypto_aes_kw::AesKwKeyData, OperationError> {
let _policy = bind_operation_policy(SecretMaterialOperation::KeyUnwrap);
match algorithm {
KeyWrapAlgorithm::Aes128Kw => {
let kek = crypto_aes_kw::Aes128KwKek::from_slice(kek).map_err(map_key_wrap_error)?;
crypto_aes_kw::unwrap_key_aes128(&kek, wrapped_key).map_err(map_key_wrap_error)
}
KeyWrapAlgorithm::Aes192Kw => {
let kek = crypto_aes_kw::Aes192KwKek::from_slice(kek).map_err(map_key_wrap_error)?;
crypto_aes_kw::unwrap_key_aes192(&kek, wrapped_key).map_err(map_key_wrap_error)
}
KeyWrapAlgorithm::Aes256Kw => {
let kek = crypto_aes_kw::Aes256KwKek::from_slice(kek).map_err(map_key_wrap_error)?;
crypto_aes_kw::unwrap_key_aes256(&kek, wrapped_key).map_err(map_key_wrap_error)
}
_ => Err(OperationError::Provider {
reason: super::ProviderErrorReason::UnsupportedAlgorithm,
}),
}
}
fn map_key_wrap_error(error: CryptoError) -> OperationError {
match error {
CryptoError::KeyWrap {
kind: KeyWrapFailureKind::InvalidKekLength,
..
} => OperationError::Primitive {
reason: PrimitiveErrorReason::InvalidKey,
},
CryptoError::KeyWrap {
kind:
KeyWrapFailureKind::InvalidPlaintextLength | KeyWrapFailureKind::InvalidWrappedLength,
..
} => OperationError::Primitive {
reason: PrimitiveErrorReason::InvalidLength,
},
CryptoError::KeyWrap {
kind: KeyWrapFailureKind::LengthOverflow,
..
} => OperationError::Primitive {
reason: PrimitiveErrorReason::LengthOverflow,
},
CryptoError::KeyWrap {
kind: KeyWrapFailureKind::IntegrityCheckFailed,
..
} => OperationError::Primitive {
reason: PrimitiveErrorReason::VerificationFailed,
},
CryptoError::KeyWrap {
kind: KeyWrapFailureKind::BackendFailure,
..
} => OperationError::Backend {
reason: BackendErrorReason::Internal,
},
CryptoError::Unsupported => OperationError::Provider {
reason: super::ProviderErrorReason::UnsupportedAlgorithm,
},
_ => OperationError::Backend {
reason: BackendErrorReason::Internal,
},
}
}