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 12, 2023
1 parent 1e04007 commit db71335
Show file tree
Hide file tree
Showing 7 changed files with 157 additions and 56 deletions.
25 changes: 12 additions & 13 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 @@ -26,7 +24,7 @@ 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 +48,9 @@ fn create_ak_public<IKC: IntoKeyCustomization>(
.build()?;

let key_builder = match key_alg {
AsymmetricAlgorithm::Rsa => PublicBuilder::new()
AsymmetricAlgorithmSelection::Rsa2048
| AsymmetricAlgorithmSelection::Rsa3072
| AsymmetricAlgorithmSelection::Rsa4096 => PublicBuilder::new()
.with_public_algorithm(PublicAlgorithm::Rsa)
.with_name_hashing_algorithm(hash_alg)
.with_object_attributes(obj_attrs)
Expand All @@ -60,15 +60,18 @@ 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_alg.try_into()?)
.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::EccP256
| AsymmetricAlgorithmSelection::EccP384
| AsymmetricAlgorithmSelection::EccP521
| AsymmetricAlgorithmSelection::EccP256Sm2 => PublicBuilder::new()
.with_public_algorithm(PublicAlgorithm::Ecc)
.with_name_hashing_algorithm(hash_alg)
.with_object_attributes(obj_attrs)
Expand All @@ -80,14 +83,10 @@ fn create_ak_public<IKC: IntoKeyCustomization>(
Some(hash_alg),
Some(0),
)?)
.with_curve(EccCurve::NistP192)
.with_curve(key_alg.try_into()?)
.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 @@ -164,7 +163,7 @@ pub fn create_ak<IKC: IntoKeyCustomization>(
ak_auth_value: Option<Auth>,
key_customization: IKC,
) -> Result<CreateKeyResult> {
let key_alg = AsymmetricAlgorithm::try_from(sign_alg).map_err(|e| {
let key_alg = AsymmetricAlgorithmSelection::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
Expand Down
54 changes: 33 additions & 21 deletions tss-esapi/src/abstraction/ek.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,7 @@ use crate::{
attributes::ObjectAttributesBuilder,
handles::{KeyHandle, NvIndexTpmHandle, TpmHandle},
interface_types::{
algorithm::{AsymmetricAlgorithm, HashingAlgorithm, PublicAlgorithm},
ecc::EccCurve,
algorithm::{AsymmetricAlgorithmSelection, HashingAlgorithm, PublicAlgorithm},
key_bits::RsaKeyBits,
resource_handles::{Hierarchy, NvAuth},
},
Expand All @@ -16,20 +15,28 @@ use crate::{
PublicBuilder, PublicEccParametersBuilder, PublicKeyRsa, PublicRsaParametersBuilder,
RsaExponent, RsaScheme, SymmetricDefinitionObject,
},
Context, Error, Result, WrapperErrorKind,
Context, Result,
};
use std::convert::TryFrom;
use std::convert::{TryFrom, TryInto};
// Source: TCG EK Credential Profile for TPM Family 2.0; Level 0 Version 2.3 Revision 2
// Section 2.2.1.4 (Low Range) for Windows compatibility
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 +72,9 @@ pub fn create_ek_public_from_default_template<IKC: IntoKeyCustomization>(
];

let key_builder = match alg {
AsymmetricAlgorithm::Rsa => PublicBuilder::new()
AsymmetricAlgorithmSelection::Rsa2048
| AsymmetricAlgorithmSelection::Rsa3072
| AsymmetricAlgorithmSelection::Rsa4096 => PublicBuilder::new()
.with_public_algorithm(PublicAlgorithm::Rsa)
.with_name_hashing_algorithm(HashingAlgorithm::Sha256)
.with_object_attributes(obj_attrs)
Expand All @@ -74,15 +83,18 @@ 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(alg.try_into()?)
.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::EccP256
| AsymmetricAlgorithmSelection::EccP384
| AsymmetricAlgorithmSelection::EccP521
| AsymmetricAlgorithmSelection::EccP256Sm2 => PublicBuilder::new()
.with_public_algorithm(PublicAlgorithm::Ecc)
.with_name_hashing_algorithm(HashingAlgorithm::Sha256)
.with_object_attributes(obj_attrs)
Expand All @@ -91,7 +103,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(alg.try_into()?)
.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 +114,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 +127,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 +140,18 @@ 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::Rsa2048 => RSA_2048_EK_CERTIFICATE_NV_INDEX,
AsymmetricAlgorithmSelection::Rsa3072 => RSA_3072_EK_CERTIFICATE_NV_INDEX,
AsymmetricAlgorithmSelection::Rsa4096 => RSA_4096_EK_CERTIFICATE_NV_INDEX,
AsymmetricAlgorithmSelection::EccP256 => ECC_P256_EK_CERTIFICATE_NV_INDEX,
AsymmetricAlgorithmSelection::EccP384 => ECC_P384_EK_CERTIFICATE_NV_INDEX,
AsymmetricAlgorithmSelection::EccP521 => ECC_P521_EK_CERTIFICATE_NV_INDEX,
AsymmetricAlgorithmSelection::EccP256Sm2 => ECC_P256_SM2_EK_CERTIFICATE_NV_INDEX,
};

let nv_idx = NvIndexTpmHandle::new(nv_idx).unwrap();
Expand Down
21 changes: 12 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,7 @@ use crate::{
constants::SessionType,
handles::{AuthHandle, KeyHandle, SessionHandle},
interface_types::{
algorithm::{AsymmetricAlgorithm, HashingAlgorithm},
algorithm::{AsymmetricAlgorithmSelection, HashingAlgorithm},
session_handles::{AuthSession, PolicySession},
},
structures::{EncryptedSecret, IdObject, SymmetricDefinition},
Expand Down Expand Up @@ -154,13 +154,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::Rsa2048,
None,
)
.or_else(|e| {
self.context
.flush_context(SessionHandle::from(session).into())?;
Err(e)
})?,
session,
))
}
Expand Down Expand Up @@ -191,7 +194,7 @@ 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::Rsa2048, None)?;
let (attesting_key_pub, _, _) = context.read_public(key_handle).or_else(|e| {
context.flush_context(key_handle.into())?;
Err(e)
Expand Down
79 changes: 79 additions & 0 deletions 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 @@ -335,6 +336,60 @@ impl TryFrom<TPMI_ALG_ASYM> for AsymmetricAlgorithm {
}
}

/// Enum representing the asymmetric algorithm interface type with specific properties.
/// Use this instead of [AsymmetricAlgorithm], which will be deprecated at some point.
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub enum AsymmetricAlgorithmSelection {
Rsa2048,
Rsa3072,
Rsa4096,
EccP256,
EccP384,
EccP521,
EccP256Sm2,
}

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::Rsa2048),
AsymmetricAlgorithm::Ecc => Ok(AsymmetricAlgorithmSelection::EccP256),
AsymmetricAlgorithm::Null => {
Err(Error::local_error(WrapperErrorKind::UnsupportedParam))
}
}
}
}

impl TryFrom<AsymmetricAlgorithmSelection> for RsaKeyBits {
type Error = Error;

fn try_from(value: AsymmetricAlgorithmSelection) -> std::result::Result<Self, Self::Error> {
match value {
AsymmetricAlgorithmSelection::Rsa2048 => Ok(RsaKeyBits::Rsa2048),
AsymmetricAlgorithmSelection::Rsa3072 => Ok(RsaKeyBits::Rsa3072),
AsymmetricAlgorithmSelection::Rsa4096 => Ok(RsaKeyBits::Rsa4096),
_ => Err(Error::local_error(WrapperErrorKind::InvalidParam)),
}
}
}

impl TryFrom<AsymmetricAlgorithmSelection> for EccCurve {
type Error = Error;

fn try_from(value: AsymmetricAlgorithmSelection) -> std::result::Result<Self, Self::Error> {
match value {
AsymmetricAlgorithmSelection::EccP256 => Ok(EccCurve::NistP256),
AsymmetricAlgorithmSelection::EccP384 => Ok(EccCurve::NistP384),
AsymmetricAlgorithmSelection::EccP521 => Ok(EccCurve::NistP521),
AsymmetricAlgorithmSelection::EccP256Sm2 => Ok(EccCurve::Sm2P256),
_ => Err(Error::local_error(WrapperErrorKind::InvalidParam)),
}
}
}

/// Enum representing the signature scheme interface type.
///
/// # Details
Expand Down Expand Up @@ -419,6 +474,30 @@ impl TryFrom<SignatureSchemeAlgorithm> for AsymmetricAlgorithm {
}
}

// A convenience conversion into AsymmetricAlgorithmSelection
// that is associated with the signature scheme.
// Currently mimics the behavior of the AsymmetricAlgorithm implementation
impl TryFrom<SignatureSchemeAlgorithm> for AsymmetricAlgorithmSelection {
type Error = Error;
fn try_from(signature_scheme: SignatureSchemeAlgorithm) -> Result<Self> {
match signature_scheme {
SignatureSchemeAlgorithm::RsaSsa => Ok(AsymmetricAlgorithmSelection::Rsa2048),
SignatureSchemeAlgorithm::RsaPss => Ok(AsymmetricAlgorithmSelection::Rsa2048),
SignatureSchemeAlgorithm::EcDsa => Ok(AsymmetricAlgorithmSelection::EccP256),
SignatureSchemeAlgorithm::EcDaa => Ok(AsymmetricAlgorithmSelection::EccP256),
SignatureSchemeAlgorithm::Sm2 => Ok(AsymmetricAlgorithmSelection::EccP256),
SignatureSchemeAlgorithm::EcSchnorr => Ok(AsymmetricAlgorithmSelection::EccP256),
_ => {
// HMAC is for symmetric algorithms
//
// Null could be converted into AsymmetricAlgorithm::Null
// but I do not know if that is useful.
Err(Error::local_error(WrapperErrorKind::InvalidParam))
}
}
}
}

/// Enum repsenting the symmetric object inetrface type.
///
/// # Details
Expand Down
14 changes: 9 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,7 @@ use tss_esapi::{
constants::SessionType,
handles::AuthHandle,
interface_types::{
algorithm::{AsymmetricAlgorithm, HashingAlgorithm, SignatureSchemeAlgorithm},
algorithm::{AsymmetricAlgorithmSelection, HashingAlgorithm, SignatureSchemeAlgorithm},
session_handles::PolicySession,
},
structures::{Auth, Digest, PublicBuilder, SymmetricDefinition},
Expand All @@ -21,7 +21,8 @@ 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::Rsa2048, None).unwrap();
ak::create_ak(
&mut context,
ek_rsa,
Expand All @@ -37,7 +38,8 @@ 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::Rsa2048, None).unwrap();
if ak::create_ak(
&mut context,
ek_rsa,
Expand All @@ -57,7 +59,8 @@ 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::Rsa2048, None).unwrap();
let ak_auth = Auth::try_from(vec![0x1, 0x2, 0x42]).unwrap();
let att_key = ak::create_ak(
&mut context,
Expand Down Expand Up @@ -158,7 +161,8 @@ 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::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(
Expand Down
Loading

0 comments on commit db71335

Please sign in to comment.