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.

Signed-off-by: Thore Sommer <[email protected]>
  • Loading branch information
THS-on committed Jun 18, 2023
1 parent 1e04007 commit 7bb9f79
Show file tree
Hide file tree
Showing 7 changed files with 151 additions and 62 deletions.
26 changes: 7 additions & 19 deletions tss-esapi/src/abstraction/ak.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,9 @@ use crate::{
handles::{AuthHandle, KeyHandle, SessionHandle},
interface_types::{
algorithm::{
AsymmetricAlgorithm, EccSchemeAlgorithm, HashingAlgorithm, PublicAlgorithm,
AsymmetricAlgorithmSelection, EccSchemeAlgorithm, HashingAlgorithm, PublicAlgorithm,
RsaSchemeAlgorithm, SignatureSchemeAlgorithm,
},
ecc::EccCurve,
key_bits::RsaKeyBits,
session_handles::PolicySession,
},
structures::{
Expand All @@ -22,11 +20,10 @@ use crate::{
},
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 +47,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 +57,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 +77,10 @@ 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));
}
};

let key_builder = if let Some(ref k) = key_customization {
Expand Down Expand Up @@ -160,16 +153,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
45 changes: 28 additions & 17 deletions tss-esapi/src/abstraction/ek.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use crate::{
attributes::ObjectAttributesBuilder,
handles::{KeyHandle, NvIndexTpmHandle, TpmHandle},
interface_types::{
algorithm::{AsymmetricAlgorithm, HashingAlgorithm, PublicAlgorithm},
algorithm::{AsymmetricAlgorithmSelection, 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
26 changes: 17 additions & 9 deletions tss-esapi/src/abstraction/transient/key_attestation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ use crate::{
constants::SessionType,
handles::{AuthHandle, KeyHandle, SessionHandle},
interface_types::{
algorithm::{AsymmetricAlgorithm, HashingAlgorithm},
algorithm::{AsymmetricAlgorithmSelection, HashingAlgorithm},
key_bits::RsaKeyBits,
session_handles::{AuthSession, PolicySession},
},
structures::{EncryptedSecret, IdObject, SymmetricDefinition},
Expand Down Expand Up @@ -154,13 +155,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 @@ -191,7 +195,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
30 changes: 29 additions & 1 deletion tss-esapi/src/interface_types/algorithm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// SPDX-License-Identifier: Apache-2.0
use crate::{
constants::AlgorithmIdentifier,
interface_types::{ecc::EccCurve, key_bits::RsaKeyBits},
tss2_esys::{
TPMI_ALG_ASYM, TPMI_ALG_ECC_SCHEME, TPMI_ALG_HASH, TPMI_ALG_KDF, TPMI_ALG_KEYEDHASH_SCHEME,
TPMI_ALG_PUBLIC, TPMI_ALG_RSA_DECRYPT, TPMI_ALG_RSA_SCHEME, TPMI_ALG_SIG_SCHEME,
Expand Down Expand Up @@ -292,7 +293,8 @@ impl TryFrom<TPMI_ALG_SYM_MODE> for SymmetricMode {
/// Enum representing the asymmetric algorithm interface type.
///
/// # Details
/// This corresponds to TPMI_ALG_ASYM
/// Use [AsymmetricAlgorithmSelection] instead where possible.
/// This corresponds to TPMI_ALG_ASYM.
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum AsymmetricAlgorithm {
Rsa,
Expand Down Expand Up @@ -335,6 +337,32 @@ impl TryFrom<TPMI_ALG_ASYM> for AsymmetricAlgorithm {
}
}

/// 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) -> std::result::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))
}
}
}
}

/// Enum representing the signature scheme interface type.
///
/// # Details
Expand Down
37 changes: 32 additions & 5 deletions tss-esapi/tests/integration_tests/abstraction_tests/ak_tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@ use tss_esapi::{
constants::SessionType,
handles::AuthHandle,
interface_types::{
algorithm::{AsymmetricAlgorithm, HashingAlgorithm, SignatureSchemeAlgorithm},
algorithm::{AsymmetricAlgorithmSelection, HashingAlgorithm, SignatureSchemeAlgorithm},
ecc::EccCurve,
key_bits::RsaKeyBits,
session_handles::PolicySession,
},
structures::{Auth, Digest, PublicBuilder, SymmetricDefinition},
Expand All @@ -21,11 +23,17 @@ use crate::common::create_ctx_without_session;
fn test_create_ak_rsa_rsa() {
let mut context = create_ctx_without_session();

let ek_rsa = ek::create_ek_object(&mut context, AsymmetricAlgorithm::Rsa, None).unwrap();
let ek_rsa = ek::create_ek_object(
&mut context,
AsymmetricAlgorithmSelection::Rsa(RsaKeyBits::Rsa2048),
None,
)
.unwrap();
ak::create_ak(
&mut context,
ek_rsa,
HashingAlgorithm::Sha256,
AsymmetricAlgorithmSelection::Rsa(RsaKeyBits::Rsa2048),
SignatureSchemeAlgorithm::RsaPss,
None,
None,
Expand All @@ -37,11 +45,17 @@ fn test_create_ak_rsa_rsa() {
fn test_create_ak_rsa_ecc() {
let mut context = create_ctx_without_session();

let ek_rsa = ek::create_ek_object(&mut context, AsymmetricAlgorithm::Rsa, None).unwrap();
let ek_rsa = ek::create_ek_object(
&mut context,
AsymmetricAlgorithmSelection::Rsa(RsaKeyBits::Rsa2048),
None,
)
.unwrap();
if ak::create_ak(
&mut context,
ek_rsa,
HashingAlgorithm::Sha256,
AsymmetricAlgorithmSelection::Ecc(EccCurve::NistP256),
SignatureSchemeAlgorithm::Sm2,
None,
None,
Expand All @@ -57,12 +71,18 @@ fn test_create_ak_rsa_ecc() {
fn test_create_and_use_ak() {
let mut context = create_ctx_without_session();

let ek_rsa = ek::create_ek_object(&mut context, AsymmetricAlgorithm::Rsa, None).unwrap();
let ek_rsa = ek::create_ek_object(
&mut context,
AsymmetricAlgorithmSelection::Rsa(RsaKeyBits::Rsa2048),
None,
)
.unwrap();
let ak_auth = Auth::try_from(vec![0x1, 0x2, 0x42]).unwrap();
let att_key = ak::create_ak(
&mut context,
ek_rsa,
HashingAlgorithm::Sha256,
AsymmetricAlgorithmSelection::Rsa(RsaKeyBits::Rsa2048),
SignatureSchemeAlgorithm::RsaPss,
Some(ak_auth.clone()),
None,
Expand Down Expand Up @@ -158,13 +178,19 @@ fn test_create_custom_ak() {
}
let mut context = create_ctx_without_session();

let ek_rsa = ek::create_ek_object(&mut context, AsymmetricAlgorithm::Rsa, None).unwrap();
let ek_rsa = ek::create_ek_object(
&mut context,
AsymmetricAlgorithmSelection::Rsa(RsaKeyBits::Rsa2048),
None,
)
.unwrap();
let ak_auth = Auth::try_from(vec![0x1, 0x2, 0x42]).unwrap();
// Without customization, no st clear
let att_key_without = ak::create_ak(
&mut context,
ek_rsa,
HashingAlgorithm::Sha256,
AsymmetricAlgorithmSelection::Rsa(RsaKeyBits::Rsa2048),
SignatureSchemeAlgorithm::RsaPss,
Some(ak_auth.clone()),
None,
Expand All @@ -181,6 +207,7 @@ fn test_create_custom_ak() {
&mut context,
ek_rsa,
HashingAlgorithm::Sha256,
AsymmetricAlgorithmSelection::Rsa(RsaKeyBits::Rsa2048),
SignatureSchemeAlgorithm::RsaPss,
Some(ak_auth),
&CustomizeKey,
Expand Down
Loading

0 comments on commit 7bb9f79

Please sign in to comment.