use aes_kw::{KekAes128, KekAes256};
use rand::{rngs::OsRng, RngCore};
use crate::error::{CasError, CasResult};
use super::cas_symmetric_encryption::{CASAES128KeyWrap, CASAES256KeyWrap};
const AES128_KEY_LEN: usize = 16;
const AES256_KEY_LEN: usize = 32;
const SEMIBLOCK_LEN: usize = 8;
pub struct CASAES128KW;
pub struct CASAES256KW;
fn validate_kw_plaintext(key_to_wrap: &[u8]) -> CasResult<()> {
if key_to_wrap.len() < 2 * SEMIBLOCK_LEN || key_to_wrap.len() % SEMIBLOCK_LEN != 0 {
return Err(CasError::InvalidInput);
}
Ok(())
}
fn validate_kw_ciphertext(wrapped_key: &[u8]) -> CasResult<()> {
if wrapped_key.len() < 3 * SEMIBLOCK_LEN || wrapped_key.len() % SEMIBLOCK_LEN != 0 {
return Err(CasError::InvalidInput);
}
Ok(())
}
fn validate_kwp_plaintext(key_to_wrap: &[u8]) -> CasResult<()> {
if key_to_wrap.is_empty() || u32::try_from(key_to_wrap.len()).is_err() {
return Err(CasError::InvalidInput);
}
Ok(())
}
fn validate_kwp_ciphertext(wrapped_key: &[u8]) -> CasResult<()> {
if wrapped_key.len() < 2 * SEMIBLOCK_LEN || wrapped_key.len() % SEMIBLOCK_LEN != 0 {
return Err(CasError::InvalidInput);
}
Ok(())
}
impl CASAES256KeyWrap for CASAES256KW {
fn generate_kek() -> Vec<u8> {
let mut os_rng = OsRng;
let mut kek = [0u8; AES256_KEY_LEN];
os_rng.fill_bytes(&mut kek);
kek.to_vec()
}
fn wrap_key(kek: Vec<u8>, key_to_wrap: Vec<u8>) -> CasResult<Vec<u8>> {
let kek = KekAes256::try_from(kek.as_slice()).map_err(|_| CasError::InvalidKey)?;
validate_kw_plaintext(&key_to_wrap)?;
kek.wrap_vec(&key_to_wrap)
.map_err(|_| CasError::EncryptionFailed)
}
fn unwrap_key(kek: Vec<u8>, wrapped_key: Vec<u8>) -> CasResult<Vec<u8>> {
let kek = KekAes256::try_from(kek.as_slice()).map_err(|_| CasError::InvalidKey)?;
validate_kw_ciphertext(&wrapped_key)?;
kek.unwrap_vec(&wrapped_key)
.map_err(|_| CasError::DecryptionFailed)
}
fn wrap_key_with_padding(kek: Vec<u8>, key_to_wrap: Vec<u8>) -> CasResult<Vec<u8>> {
let kek = KekAes256::try_from(kek.as_slice()).map_err(|_| CasError::InvalidKey)?;
validate_kwp_plaintext(&key_to_wrap)?;
kek.wrap_with_padding_vec(&key_to_wrap)
.map_err(|_| CasError::EncryptionFailed)
}
fn unwrap_key_with_padding(kek: Vec<u8>, wrapped_key: Vec<u8>) -> CasResult<Vec<u8>> {
let kek = KekAes256::try_from(kek.as_slice()).map_err(|_| CasError::InvalidKey)?;
validate_kwp_ciphertext(&wrapped_key)?;
kek.unwrap_with_padding_vec(&wrapped_key)
.map_err(|_| CasError::DecryptionFailed)
}
}
impl CASAES128KeyWrap for CASAES128KW {
fn generate_kek() -> Vec<u8> {
let mut os_rng = OsRng;
let mut kek = [0u8; AES128_KEY_LEN];
os_rng.fill_bytes(&mut kek);
kek.to_vec()
}
fn wrap_key(kek: Vec<u8>, key_to_wrap: Vec<u8>) -> CasResult<Vec<u8>> {
let kek = KekAes128::try_from(kek.as_slice()).map_err(|_| CasError::InvalidKey)?;
validate_kw_plaintext(&key_to_wrap)?;
kek.wrap_vec(&key_to_wrap)
.map_err(|_| CasError::EncryptionFailed)
}
fn unwrap_key(kek: Vec<u8>, wrapped_key: Vec<u8>) -> CasResult<Vec<u8>> {
let kek = KekAes128::try_from(kek.as_slice()).map_err(|_| CasError::InvalidKey)?;
validate_kw_ciphertext(&wrapped_key)?;
kek.unwrap_vec(&wrapped_key)
.map_err(|_| CasError::DecryptionFailed)
}
fn wrap_key_with_padding(kek: Vec<u8>, key_to_wrap: Vec<u8>) -> CasResult<Vec<u8>> {
let kek = KekAes128::try_from(kek.as_slice()).map_err(|_| CasError::InvalidKey)?;
validate_kwp_plaintext(&key_to_wrap)?;
kek.wrap_with_padding_vec(&key_to_wrap)
.map_err(|_| CasError::EncryptionFailed)
}
fn unwrap_key_with_padding(kek: Vec<u8>, wrapped_key: Vec<u8>) -> CasResult<Vec<u8>> {
let kek = KekAes128::try_from(kek.as_slice()).map_err(|_| CasError::InvalidKey)?;
validate_kwp_ciphertext(&wrapped_key)?;
kek.unwrap_with_padding_vec(&wrapped_key)
.map_err(|_| CasError::DecryptionFailed)
}
}