use crate::{
interface_types::{
algorithm::{HashingAlgorithm, SymmetricAlgorithm, SymmetricMode, SymmetricObject},
key_bits::{AesKeyBits, CamelliaKeyBits, Sm4KeyBits},
},
tss2_esys::{TPMT_SYM_DEF, TPMT_SYM_DEF_OBJECT, TPMU_SYM_KEY_BITS, TPMU_SYM_MODE},
Error, Result, WrapperErrorKind,
};
use std::convert::{TryFrom, TryInto};
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
pub enum SymmetricDefinition {
Aes {
key_bits: AesKeyBits,
mode: SymmetricMode,
},
Sm4 {
key_bits: Sm4KeyBits,
mode: SymmetricMode,
},
Camellia {
key_bits: CamelliaKeyBits,
mode: SymmetricMode,
},
Xor {
hashing_algorithm: HashingAlgorithm,
},
Null,
}
impl SymmetricDefinition {
pub const AES_128_CFB: SymmetricDefinition = SymmetricDefinition::Aes {
key_bits: AesKeyBits::Aes128,
mode: SymmetricMode::Cfb,
};
pub const AES_256_CFB: SymmetricDefinition = SymmetricDefinition::Aes {
key_bits: AesKeyBits::Aes256,
mode: SymmetricMode::Cfb,
};
}
impl TryFrom<SymmetricDefinition> for TPMT_SYM_DEF {
type Error = Error;
fn try_from(symmetric_definition: SymmetricDefinition) -> Result<TPMT_SYM_DEF> {
match symmetric_definition {
SymmetricDefinition::Aes { key_bits, mode } => Ok(TPMT_SYM_DEF {
algorithm: SymmetricAlgorithm::Aes.into(),
keyBits: TPMU_SYM_KEY_BITS {
aes: key_bits.into(),
},
mode: TPMU_SYM_MODE { aes: mode.into() },
}),
SymmetricDefinition::Sm4 { key_bits, mode } => Ok(TPMT_SYM_DEF {
algorithm: SymmetricAlgorithm::Sm4.into(),
keyBits: TPMU_SYM_KEY_BITS {
sm4: key_bits.into(),
},
mode: TPMU_SYM_MODE { sm4: mode.into() },
}),
SymmetricDefinition::Camellia { key_bits, mode } => Ok(TPMT_SYM_DEF {
algorithm: SymmetricAlgorithm::Camellia.into(),
keyBits: TPMU_SYM_KEY_BITS {
camellia: key_bits.into(),
},
mode: TPMU_SYM_MODE {
camellia: mode.into(),
},
}),
SymmetricDefinition::Xor { hashing_algorithm } => Ok(TPMT_SYM_DEF {
algorithm: SymmetricAlgorithm::Xor.into(),
keyBits: TPMU_SYM_KEY_BITS {
exclusiveOr: if hashing_algorithm != HashingAlgorithm::Null {
hashing_algorithm.into()
} else {
return Err(Error::local_error(WrapperErrorKind::InvalidParam));
},
},
mode: Default::default(),
}),
SymmetricDefinition::Null => Ok(TPMT_SYM_DEF {
algorithm: SymmetricAlgorithm::Null.into(),
keyBits: Default::default(),
mode: Default::default(),
}),
}
}
}
impl TryFrom<TPMT_SYM_DEF> for SymmetricDefinition {
type Error = Error;
fn try_from(tpmt_sym_def: TPMT_SYM_DEF) -> Result<SymmetricDefinition> {
match SymmetricAlgorithm::try_from(tpmt_sym_def.algorithm)? {
SymmetricAlgorithm::Aes => Ok(SymmetricDefinition::Aes {
key_bits: unsafe { tpmt_sym_def.keyBits.aes }.try_into()?,
mode: unsafe { tpmt_sym_def.mode.aes }.try_into()?,
}),
SymmetricAlgorithm::Sm4 => Ok(SymmetricDefinition::Sm4 {
key_bits: unsafe { tpmt_sym_def.keyBits.sm4 }.try_into()?,
mode: unsafe { tpmt_sym_def.mode.sm4 }.try_into()?,
}),
SymmetricAlgorithm::Camellia => Ok(SymmetricDefinition::Camellia {
key_bits: unsafe { tpmt_sym_def.keyBits.camellia }.try_into()?,
mode: unsafe { tpmt_sym_def.mode.camellia }.try_into()?,
}),
SymmetricAlgorithm::Xor => Ok(SymmetricDefinition::Xor {
hashing_algorithm: HashingAlgorithm::try_from(unsafe {
tpmt_sym_def.keyBits.exclusiveOr
})
.and_then(|ha| {
if ha != HashingAlgorithm::Null {
Ok(ha)
} else {
Err(Error::local_error(WrapperErrorKind::InvalidParam))
}
})?,
}),
SymmetricAlgorithm::Null => Ok(SymmetricDefinition::Null),
SymmetricAlgorithm::Tdes => {
Err(Error::local_error(WrapperErrorKind::WrongValueFromTpm))
}
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum SymmetricDefinitionObject {
Aes {
key_bits: AesKeyBits,
mode: SymmetricMode,
},
Sm4 {
key_bits: Sm4KeyBits,
mode: SymmetricMode,
},
Camellia {
key_bits: CamelliaKeyBits,
mode: SymmetricMode,
},
Null,
}
impl SymmetricDefinitionObject {
pub const AES_128_CFB: SymmetricDefinitionObject = SymmetricDefinitionObject::Aes {
key_bits: AesKeyBits::Aes128,
mode: SymmetricMode::Cfb,
};
pub const AES_256_CFB: SymmetricDefinitionObject = SymmetricDefinitionObject::Aes {
key_bits: AesKeyBits::Aes256,
mode: SymmetricMode::Cfb,
};
pub(crate) fn is_null(&self) -> bool {
matches!(self, Self::Null)
}
}
impl Default for SymmetricDefinitionObject {
fn default() -> Self {
Self::Null
}
}
impl From<SymmetricDefinitionObject> for TPMT_SYM_DEF_OBJECT {
fn from(symmetric_definition_object: SymmetricDefinitionObject) -> TPMT_SYM_DEF_OBJECT {
match symmetric_definition_object {
SymmetricDefinitionObject::Aes { key_bits, mode } => TPMT_SYM_DEF_OBJECT {
algorithm: SymmetricAlgorithm::Aes.into(),
keyBits: TPMU_SYM_KEY_BITS {
aes: key_bits.into(),
},
mode: TPMU_SYM_MODE { aes: mode.into() },
},
SymmetricDefinitionObject::Sm4 { key_bits, mode } => TPMT_SYM_DEF_OBJECT {
algorithm: SymmetricAlgorithm::Sm4.into(),
keyBits: TPMU_SYM_KEY_BITS {
sm4: key_bits.into(),
},
mode: TPMU_SYM_MODE { sm4: mode.into() },
},
SymmetricDefinitionObject::Camellia { key_bits, mode } => TPMT_SYM_DEF_OBJECT {
algorithm: SymmetricAlgorithm::Camellia.into(),
keyBits: TPMU_SYM_KEY_BITS {
camellia: key_bits.into(),
},
mode: TPMU_SYM_MODE {
camellia: mode.into(),
},
},
SymmetricDefinitionObject::Null => TPMT_SYM_DEF_OBJECT {
algorithm: SymmetricAlgorithm::Null.into(),
keyBits: Default::default(),
mode: Default::default(),
},
}
}
}
impl From<SymmetricDefinitionObject> for SymmetricDefinition {
fn from(sym_def_obj: SymmetricDefinitionObject) -> Self {
match sym_def_obj {
SymmetricDefinitionObject::Null => SymmetricDefinition::Null,
SymmetricDefinitionObject::Camellia { key_bits, mode } => {
SymmetricDefinition::Camellia { key_bits, mode }
}
SymmetricDefinitionObject::Aes { key_bits, mode } => {
SymmetricDefinition::Aes { key_bits, mode }
}
SymmetricDefinitionObject::Sm4 { key_bits, mode } => {
SymmetricDefinition::Sm4 { key_bits, mode }
}
}
}
}
impl TryFrom<TPMT_SYM_DEF_OBJECT> for SymmetricDefinitionObject {
type Error = Error;
fn try_from(tpmt_sym_def_object: TPMT_SYM_DEF_OBJECT) -> Result<SymmetricDefinitionObject> {
match SymmetricObject::try_from(tpmt_sym_def_object.algorithm)? {
SymmetricObject::Aes => Ok(SymmetricDefinitionObject::Aes {
key_bits: unsafe { tpmt_sym_def_object.keyBits.aes }.try_into()?,
mode: unsafe { tpmt_sym_def_object.mode.aes }.try_into()?,
}),
SymmetricObject::Sm4 => Ok(SymmetricDefinitionObject::Sm4 {
key_bits: unsafe { tpmt_sym_def_object.keyBits.sm4 }.try_into()?,
mode: unsafe { tpmt_sym_def_object.mode.sm4 }.try_into()?,
}),
SymmetricObject::Camellia => Ok(SymmetricDefinitionObject::Camellia {
key_bits: unsafe { tpmt_sym_def_object.keyBits.camellia }.try_into()?,
mode: unsafe { tpmt_sym_def_object.mode.camellia }.try_into()?,
}),
SymmetricObject::Null => Ok(SymmetricDefinitionObject::Null),
SymmetricObject::Tdes => {
Err(Error::local_error(WrapperErrorKind::WrongValueFromTpm))
}
}
}
}