Skip to content

Commit

Permalink
ek, ak abstractions: allow to specficy exact key type
Browse files Browse the repository at this point in the history
This adds support other keys than RSA2048 and ECC Nist P256.

The difference between this commit and the original
is that it has been adopted to be compatible with
the 7.x.y branch(Jesper Brynolf).

Co-authored-by: Jesper Brynolf <[email protected]>
Signed-off-by: Thore Sommer <[email protected]>
  • Loading branch information
THS-on and Superhepper committed Oct 2, 2024
1 parent 96f6855 commit 9d306a0
Show file tree
Hide file tree
Showing 8 changed files with 169 additions and 75 deletions.
37 changes: 14 additions & 23 deletions tss-esapi/src/abstraction/ak.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,31 +2,30 @@
// SPDX-License-Identifier: Apache-2.0

use crate::{
abstraction::{cipher::Cipher, IntoKeyCustomization, KeyCustomization},
abstraction::{
cipher::Cipher, AsymmetricAlgorithmSelection, IntoKeyCustomization, KeyCustomization,
},
attributes::{ObjectAttributesBuilder, SessionAttributesBuilder},
constants::{AlgorithmIdentifier, SessionType},
handles::{AuthHandle, KeyHandle, SessionHandle},
interface_types::{
algorithm::{
AsymmetricAlgorithm, EccSchemeAlgorithm, HashingAlgorithm, PublicAlgorithm,
RsaSchemeAlgorithm, SignatureSchemeAlgorithm,
EccSchemeAlgorithm, HashingAlgorithm, PublicAlgorithm, RsaSchemeAlgorithm,
SignatureSchemeAlgorithm,
},
ecc::EccCurve,
key_bits::RsaKeyBits,
session_handles::PolicySession,
},
structures::{
Auth, CreateKeyResult, EccScheme, KeyDerivationFunctionScheme, Private, Public,
Auth, CreateKeyResult, EccPoint, EccScheme, KeyDerivationFunctionScheme, Private, Public,
PublicBuilder, PublicEccParametersBuilder, PublicKeyRsa, PublicRsaParametersBuilder,
RsaExponent, RsaScheme, SymmetricDefinitionObject,
},
Context, Error, Result, WrapperErrorKind,
};
use log::error;
use std::convert::{TryFrom, TryInto};

fn create_ak_public<IKC: IntoKeyCustomization>(
key_alg: AsymmetricAlgorithm,
key_alg: AsymmetricAlgorithmSelection,
hash_alg: HashingAlgorithm,
sign_alg: SignatureSchemeAlgorithm,
key_customization: IKC,
Expand All @@ -50,7 +49,7 @@ fn create_ak_public<IKC: IntoKeyCustomization>(
.build()?;

let key_builder = match key_alg {
AsymmetricAlgorithm::Rsa => PublicBuilder::new()
AsymmetricAlgorithmSelection::Rsa(key_bits) => PublicBuilder::new()
.with_public_algorithm(PublicAlgorithm::Rsa)
.with_name_hashing_algorithm(hash_alg)
.with_object_attributes(obj_attrs)
Expand All @@ -60,15 +59,15 @@ fn create_ak_public<IKC: IntoKeyCustomization>(
RsaSchemeAlgorithm::try_from(AlgorithmIdentifier::from(sign_alg))?,
Some(hash_alg),
)?)
.with_key_bits(RsaKeyBits::Rsa2048)
.with_key_bits(key_bits)
.with_exponent(RsaExponent::default())
.with_is_signing_key(obj_attrs.sign_encrypt())
.with_is_decryption_key(obj_attrs.decrypt())
.with_restricted(obj_attrs.restricted())
.build()?,
)
.with_rsa_unique_identifier(PublicKeyRsa::default()),
AsymmetricAlgorithm::Ecc => PublicBuilder::new()
AsymmetricAlgorithmSelection::Ecc(ecc_curve) => PublicBuilder::new()
.with_public_algorithm(PublicAlgorithm::Ecc)
.with_name_hashing_algorithm(hash_alg)
.with_object_attributes(obj_attrs)
Expand All @@ -80,14 +79,11 @@ fn create_ak_public<IKC: IntoKeyCustomization>(
Some(hash_alg),
Some(0),
)?)
.with_curve(EccCurve::NistP192)
.with_curve(ecc_curve)
.with_key_derivation_function_scheme(KeyDerivationFunctionScheme::Null)
.build()?,
),
AsymmetricAlgorithm::Null => {
// TODO: Figure out what to with Null.
return Err(Error::local_error(WrapperErrorKind::UnsupportedParam));
}
)
.with_ecc_unique_identifier(EccPoint::default()),
};

let key_builder = if let Some(ref k) = key_customization {
Expand Down Expand Up @@ -160,16 +156,11 @@ pub fn create_ak<IKC: IntoKeyCustomization>(
context: &mut Context,
parent: KeyHandle,
hash_alg: HashingAlgorithm,
key_alg: AsymmetricAlgorithmSelection,
sign_alg: SignatureSchemeAlgorithm,
ak_auth_value: Option<Auth>,
key_customization: IKC,
) -> Result<CreateKeyResult> {
let key_alg = AsymmetricAlgorithm::try_from(sign_alg).map_err(|e| {
// sign_alg is either HMAC or Null.
error!("Could not retrieve asymmetric algorithm for provided signature scheme");
e
})?;

let ak_pub = create_ak_public(key_alg, hash_alg, sign_alg, key_customization)?;

let policy_auth_session = context
Expand Down
47 changes: 29 additions & 18 deletions tss-esapi/src/abstraction/ek.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,11 @@
// SPDX-License-Identifier: Apache-2.0

use crate::{
abstraction::{nv, IntoKeyCustomization, KeyCustomization},
abstraction::{nv, AsymmetricAlgorithmSelection, IntoKeyCustomization, KeyCustomization},
attributes::ObjectAttributesBuilder,
handles::{KeyHandle, NvIndexTpmHandle, TpmHandle},
interface_types::{
algorithm::{AsymmetricAlgorithm, HashingAlgorithm, PublicAlgorithm},
algorithm::{HashingAlgorithm, PublicAlgorithm},
ecc::EccCurve,
key_bits::RsaKeyBits,
resource_handles::{Hierarchy, NvAuth},
Expand All @@ -24,12 +24,20 @@ use std::convert::TryFrom;
const RSA_2048_EK_CERTIFICATE_NV_INDEX: u32 = 0x01c00002;
const ECC_P256_EK_CERTIFICATE_NV_INDEX: u32 = 0x01c0000a;

// Source: TCG EK Credential Profile for TPM Family 2.0; Level 0 Version 2.3 Revision 2
// Section 2.2.1.5 (High Range)
const ECC_P384_EK_CERTIFICATE_NV_INDEX: u32 = 0x01c00016;
const ECC_P521_EK_CERTIFICATE_NV_INDEX: u32 = 0x01c00018;
const ECC_P256_SM2_EK_CERTIFICATE_NV_INDEX: u32 = 0x01c0001a;
const RSA_3072_EK_CERTIFICATE_NV_INDEX: u32 = 0x01c0001c;
const RSA_4096_EK_CERTIFICATE_NV_INDEX: u32 = 0x01c0001e;

/// Get the [`Public`] representing a default Endorsement Key
///
/// Source: TCG EK Credential Profile for TPM Family 2.0; Level 0 Version 2.3 Revision 2
/// Appendix B.3.3 and B.3.4
pub fn create_ek_public_from_default_template<IKC: IntoKeyCustomization>(
alg: AsymmetricAlgorithm,
alg: AsymmetricAlgorithmSelection,
key_customization: IKC,
) -> Result<Public> {
let key_customization = key_customization.into_key_customization();
Expand Down Expand Up @@ -65,7 +73,7 @@ pub fn create_ek_public_from_default_template<IKC: IntoKeyCustomization>(
];

let key_builder = match alg {
AsymmetricAlgorithm::Rsa => PublicBuilder::new()
AsymmetricAlgorithmSelection::Rsa(key_bits) => PublicBuilder::new()
.with_public_algorithm(PublicAlgorithm::Rsa)
.with_name_hashing_algorithm(HashingAlgorithm::Sha256)
.with_object_attributes(obj_attrs)
Expand All @@ -74,15 +82,15 @@ pub fn create_ek_public_from_default_template<IKC: IntoKeyCustomization>(
PublicRsaParametersBuilder::new()
.with_symmetric(SymmetricDefinitionObject::AES_128_CFB)
.with_scheme(RsaScheme::Null)
.with_key_bits(RsaKeyBits::Rsa2048)
.with_key_bits(key_bits)
.with_exponent(RsaExponent::default())
.with_is_signing_key(obj_attrs.sign_encrypt())
.with_is_decryption_key(obj_attrs.decrypt())
.with_restricted(obj_attrs.decrypt())
.build()?,
)
.with_rsa_unique_identifier(PublicKeyRsa::new_empty_with_size(RsaKeyBits::Rsa2048)),
AsymmetricAlgorithm::Ecc => PublicBuilder::new()
AsymmetricAlgorithmSelection::Ecc(ecc_curve) => PublicBuilder::new()
.with_public_algorithm(PublicAlgorithm::Ecc)
.with_name_hashing_algorithm(HashingAlgorithm::Sha256)
.with_object_attributes(obj_attrs)
Expand All @@ -91,7 +99,7 @@ pub fn create_ek_public_from_default_template<IKC: IntoKeyCustomization>(
PublicEccParametersBuilder::new()
.with_symmetric(SymmetricDefinitionObject::AES_128_CFB)
.with_ecc_scheme(EccScheme::Null)
.with_curve(EccCurve::NistP256)
.with_curve(ecc_curve)
.with_key_derivation_function_scheme(KeyDerivationFunctionScheme::Null)
.with_is_signing_key(obj_attrs.sign_encrypt())
.with_is_decryption_key(obj_attrs.decrypt())
Expand All @@ -102,10 +110,6 @@ pub fn create_ek_public_from_default_template<IKC: IntoKeyCustomization>(
EccParameter::try_from(vec![0u8; 32])?,
EccParameter::try_from(vec![0u8; 32])?,
)),
AsymmetricAlgorithm::Null => {
// TDOD: Figure out what to with Null.
return Err(Error::local_error(WrapperErrorKind::UnsupportedParam));
}
};

let key_builder = if let Some(ref k) = key_customization {
Expand All @@ -119,7 +123,7 @@ pub fn create_ek_public_from_default_template<IKC: IntoKeyCustomization>(
/// Create the Endorsement Key object from the specification templates
pub fn create_ek_object<IKC: IntoKeyCustomization>(
context: &mut Context,
alg: AsymmetricAlgorithm,
alg: AsymmetricAlgorithmSelection,
key_customization: IKC,
) -> Result<KeyHandle> {
let ek_public = create_ek_public_from_default_template(alg, key_customization)?;
Expand All @@ -132,14 +136,21 @@ pub fn create_ek_object<IKC: IntoKeyCustomization>(
}

/// Retrieve the Endorsement Key public certificate from the TPM
pub fn retrieve_ek_pubcert(context: &mut Context, alg: AsymmetricAlgorithm) -> Result<Vec<u8>> {
pub fn retrieve_ek_pubcert(
context: &mut Context,
alg: AsymmetricAlgorithmSelection,
) -> Result<Vec<u8>> {
let nv_idx = match alg {
AsymmetricAlgorithm::Rsa => RSA_2048_EK_CERTIFICATE_NV_INDEX,
AsymmetricAlgorithm::Ecc => ECC_P256_EK_CERTIFICATE_NV_INDEX,
AsymmetricAlgorithm::Null => {
// TDOD: Figure out what to with Null.
return Err(Error::local_error(WrapperErrorKind::UnsupportedParam));
AsymmetricAlgorithmSelection::Rsa(RsaKeyBits::Rsa2048) => RSA_2048_EK_CERTIFICATE_NV_INDEX,
AsymmetricAlgorithmSelection::Rsa(RsaKeyBits::Rsa3072) => RSA_3072_EK_CERTIFICATE_NV_INDEX,
AsymmetricAlgorithmSelection::Rsa(RsaKeyBits::Rsa4096) => RSA_4096_EK_CERTIFICATE_NV_INDEX,
AsymmetricAlgorithmSelection::Ecc(EccCurve::NistP256) => ECC_P256_EK_CERTIFICATE_NV_INDEX,
AsymmetricAlgorithmSelection::Ecc(EccCurve::NistP384) => ECC_P384_EK_CERTIFICATE_NV_INDEX,
AsymmetricAlgorithmSelection::Ecc(EccCurve::NistP521) => ECC_P521_EK_CERTIFICATE_NV_INDEX,
AsymmetricAlgorithmSelection::Ecc(EccCurve::Sm2P256) => {
ECC_P256_SM2_EK_CERTIFICATE_NV_INDEX
}
_ => return Err(Error::local_error(WrapperErrorKind::UnsupportedParam)),
};

let nv_idx = NvIndexTpmHandle::new(nv_idx).unwrap();
Expand Down
37 changes: 35 additions & 2 deletions tss-esapi/src/abstraction/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,16 @@ pub mod pcr;
pub mod public;
pub mod transient;

use crate::{attributes::ObjectAttributesBuilder, structures::PublicBuilder};
use std::convert::TryFrom;

/// KeyCustomizaion allows to adjust how a key is going to be created
use crate::{
attributes::ObjectAttributesBuilder,
interface_types::{algorithm::AsymmetricAlgorithm, ecc::EccCurve, key_bits::RsaKeyBits},
structures::PublicBuilder,
Error, WrapperErrorKind,
};

/// KeyCustomization allows to adjust how a key is going to be created
pub trait KeyCustomization {
/// Alter the attributes used on key creation
fn attributes(&self, attributes_builder: ObjectAttributesBuilder) -> ObjectAttributesBuilder {
Expand Down Expand Up @@ -60,3 +67,29 @@ impl IntoKeyCustomization for Option<DefaultKey> {
None
}
}

/// Enum representing the asymmetric algorithm interface type with specific properties.
///
/// # Details
/// Use this instead of [AsymmetricAlgorithm].
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
pub enum AsymmetricAlgorithmSelection {
Rsa(RsaKeyBits),
Ecc(EccCurve),
}

/// The conversion assumes for RSA 2048 bit size and for ECC the Nist P256 curve,
/// which matches the defaults in tpm2-tools.
impl TryFrom<AsymmetricAlgorithm> for AsymmetricAlgorithmSelection {
type Error = Error;

fn try_from(value: AsymmetricAlgorithm) -> Result<Self, Self::Error> {
match value {
AsymmetricAlgorithm::Rsa => Ok(AsymmetricAlgorithmSelection::Rsa(RsaKeyBits::Rsa2048)),
AsymmetricAlgorithm::Ecc => Ok(AsymmetricAlgorithmSelection::Ecc(EccCurve::NistP256)),
AsymmetricAlgorithm::Null => {
Err(Error::local_error(WrapperErrorKind::UnsupportedParam))
}
}
}
}
28 changes: 18 additions & 10 deletions tss-esapi/src/abstraction/transient/key_attestation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@
// SPDX-License-Identifier: Apache-2.0
use super::{ObjectWrapper, TransientKeyContext};
use crate::{
abstraction::ek,
abstraction::{ek, AsymmetricAlgorithmSelection},
constants::SessionType,
handles::{AuthHandle, KeyHandle, SessionHandle},
interface_types::{
algorithm::{AsymmetricAlgorithm, HashingAlgorithm},
algorithm::HashingAlgorithm,
key_bits::RsaKeyBits,
session_handles::{AuthSession, PolicySession},
},
structures::{EncryptedSecret, IdObject, SymmetricDefinition},
Expand Down Expand Up @@ -151,13 +152,16 @@ impl TransientKeyContext {
None,
);
Ok((
ek::create_ek_object(&mut self.context, AsymmetricAlgorithm::Rsa, None).or_else(
|e| {
self.context
.flush_context(SessionHandle::from(session).into())?;
Err(e)
},
)?,
ek::create_ek_object(
&mut self.context,
AsymmetricAlgorithmSelection::Rsa(RsaKeyBits::Rsa2048),
None,
)
.or_else(|e| {
self.context
.flush_context(SessionHandle::from(session).into())?;
Err(e)
})?,
session,
))
}
Expand Down Expand Up @@ -188,7 +192,11 @@ impl TransientKeyContext {
}

fn get_ek_object_public(context: &mut crate::Context) -> Result<PublicKey> {
let key_handle = ek::create_ek_object(context, AsymmetricAlgorithm::Rsa, None)?;
let key_handle = ek::create_ek_object(
context,
AsymmetricAlgorithmSelection::Rsa(RsaKeyBits::Rsa2048),
None,
)?;
let (attesting_key_pub, _, _) = context.read_public(key_handle).or_else(|e| {
context.flush_context(key_handle.into())?;
Err(e)
Expand Down
3 changes: 2 additions & 1 deletion tss-esapi/src/interface_types/algorithm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -292,7 +292,8 @@ impl TryFrom<TPMI_ALG_SYM_MODE> for SymmetricMode {
/// Enum representing the asymmetric algorithm interface type.
///
/// # Details
/// This corresponds to TPMI_ALG_ASYM
/// Use [crate::abstraction::AsymmetricAlgorithmSelection] instead where possible.
/// This corresponds to TPMI_ALG_ASYM.
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum AsymmetricAlgorithm {
Rsa,
Expand Down
Loading

0 comments on commit 9d306a0

Please sign in to comment.