Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Align ek abstraction with TCG EK Credential profile #552

Merged
merged 5 commits into from
Oct 30, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
99 changes: 88 additions & 11 deletions tss-esapi/src/abstraction/ak.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,7 @@
// SPDX-License-Identifier: Apache-2.0

use crate::{
abstraction::{
cipher::Cipher, AsymmetricAlgorithmSelection, IntoKeyCustomization, KeyCustomization,
},
abstraction::{AsymmetricAlgorithmSelection, IntoKeyCustomization, KeyCustomization},
attributes::{ObjectAttributesBuilder, SessionAttributesBuilder},
constants::{AlgorithmIdentifier, SessionType},
handles::{AuthHandle, KeyHandle, SessionHandle},
Expand All @@ -16,13 +14,46 @@ use crate::{
session_handles::PolicySession,
},
structures::{
Auth, CreateKeyResult, EccPoint, EccScheme, KeyDerivationFunctionScheme, Private, Public,
PublicBuilder, PublicEccParametersBuilder, PublicKeyRsa, PublicRsaParametersBuilder,
RsaExponent, RsaScheme, SymmetricDefinitionObject,
Auth, CreateKeyResult, DigestList, EccPoint, EccScheme, KeyDerivationFunctionScheme,
Private, Public, PublicBuilder, PublicEccParametersBuilder, PublicKeyRsa,
PublicRsaParametersBuilder, RsaExponent, RsaScheme, SymmetricDefinitionObject,
},
Context, Error, Result, WrapperErrorKind,
};
use std::convert::{TryFrom, TryInto};
use std::convert::TryFrom;

// Source: TCG EK Credential Profile for TPM Family 2.0; Level 0 Version 2.5 Revision 2
// Section B.6
const POLICY_A_SHA384: [u8; 48] = [
0x8b, 0xbf, 0x22, 0x66, 0x53, 0x7c, 0x17, 0x1c, 0xb5, 0x6e, 0x40, 0x3c, 0x4d, 0xc1, 0xd4, 0xb6,
0x4f, 0x43, 0x26, 0x11, 0xdc, 0x38, 0x6e, 0x6f, 0x53, 0x20, 0x50, 0xc3, 0x27, 0x8c, 0x93, 0x0e,
0x14, 0x3e, 0x8b, 0xb1, 0x13, 0x38, 0x24, 0xcc, 0xb4, 0x31, 0x05, 0x38, 0x71, 0xc6, 0xdb, 0x53,
];
const POLICY_A_SHA512: [u8; 64] = [
0x1e, 0x3b, 0x76, 0x50, 0x2c, 0x8a, 0x14, 0x25, 0xaa, 0x0b, 0x7b, 0x3f, 0xc6, 0x46, 0xa1, 0xb0,
0xfa, 0xe0, 0x63, 0xb0, 0x3b, 0x53, 0x68, 0xf9, 0xc4, 0xcd, 0xde, 0xca, 0xff, 0x08, 0x91, 0xdd,
0x68, 0x2b, 0xac, 0x1a, 0x85, 0xd4, 0xd8, 0x32, 0xb7, 0x81, 0xea, 0x45, 0x19, 0x15, 0xde, 0x5f,
0xc5, 0xbf, 0x0d, 0xc4, 0xa1, 0x91, 0x7c, 0xd4, 0x2f, 0xa0, 0x41, 0xe3, 0xf9, 0x98, 0xe0, 0xee,
];
const POLICY_A_SM3_256: [u8; 32] = [
0xc6, 0x7f, 0x7d, 0x35, 0xf6, 0x6f, 0x3b, 0xec, 0x13, 0xc8, 0x9f, 0xe8, 0x98, 0x92, 0x1c, 0x65,
0x1b, 0x0c, 0xb5, 0xa3, 0x8a, 0x92, 0x69, 0x0a, 0x62, 0xa4, 0x3c, 0x00, 0x12, 0xe4, 0xfb, 0x8b,
];
const POLICY_C_SHA384: [u8; 48] = [
0xd6, 0x03, 0x2c, 0xe6, 0x1f, 0x2f, 0xb3, 0xc2, 0x40, 0xeb, 0x3c, 0xf6, 0xa3, 0x32, 0x37, 0xef,
0x2b, 0x6a, 0x16, 0xf4, 0x29, 0x3c, 0x22, 0xb4, 0x55, 0xe2, 0x61, 0xcf, 0xfd, 0x21, 0x7a, 0xd5,
0xb4, 0x94, 0x7c, 0x2d, 0x73, 0xe6, 0x30, 0x05, 0xee, 0xd2, 0xdc, 0x2b, 0x35, 0x93, 0xd1, 0x65,
];
const POLICY_C_SHA512: [u8; 64] = [
0x58, 0x9e, 0xe1, 0xe1, 0x46, 0x54, 0x47, 0x16, 0xe8, 0xde, 0xaf, 0xe6, 0xdb, 0x24, 0x7b, 0x01,
0xb8, 0x1e, 0x9f, 0x9c, 0x7d, 0xd1, 0x6b, 0x81, 0x4a, 0xa1, 0x59, 0x13, 0x87, 0x49, 0x10, 0x5f,
0xba, 0x53, 0x88, 0xdd, 0x1d, 0xea, 0x70, 0x2f, 0x35, 0x24, 0x0c, 0x18, 0x49, 0x33, 0x12, 0x1e,
0x2c, 0x61, 0xb8, 0xf5, 0x0d, 0x3e, 0xf9, 0x13, 0x93, 0xa4, 0x9a, 0x38, 0xc3, 0xf7, 0x3f, 0xc8,
];
const POLICY_C_SM3_256: [u8; 32] = [
0x2d, 0x4e, 0x81, 0x57, 0x8c, 0x35, 0x31, 0xd9, 0xbd, 0x1c, 0xdd, 0x7d, 0x02, 0xba, 0x29, 0x8d,
0x56, 0x99, 0xa3, 0xe3, 0x9f, 0xc3, 0x55, 0x1b, 0xfe, 0xff, 0xcf, 0x13, 0x2b, 0x49, 0xe1, 0x1d,
];

fn create_ak_public<IKC: IntoKeyCustomization>(
key_alg: AsymmetricAlgorithmSelection,
Expand Down Expand Up @@ -99,6 +130,35 @@ fn create_ak_public<IKC: IntoKeyCustomization>(
key_builder.build()
}

// extracts the hashing and sysmmetric algorithm from parent and constructs the correct DigestList for OR policy
fn session_config(
context: &mut Context,
parent: KeyHandle,
) -> Result<(HashingAlgorithm, SymmetricDefinitionObject, DigestList)> {
let parent_hash_alg = context.read_public(parent)?.0.name_hashing_algorithm();
let parent_symmetric = context.read_public(parent)?.0.symmetric_algorithm()?;

let mut policy_digests = DigestList::new();

match parent_hash_alg {
HashingAlgorithm::Sha384 => {
policy_digests.add(POLICY_A_SHA384.into())?;
policy_digests.add(POLICY_C_SHA384.into())?
}
HashingAlgorithm::Sha512 => {
policy_digests.add(POLICY_A_SHA512.into())?;
policy_digests.add(POLICY_C_SHA512.into())?
}
HashingAlgorithm::Sm3_256 => {
policy_digests.add(POLICY_A_SM3_256.into())?;
policy_digests.add(POLICY_C_SM3_256.into())?
}
_ => (),
};

Ok((parent_hash_alg, parent_symmetric, policy_digests))
}

/// This loads an Attestation Key previously generated under the Endorsement hierarchy
pub fn load_ak(
context: &mut Context,
Expand All @@ -107,14 +167,16 @@ pub fn load_ak(
private: Private,
public: Public,
) -> Result<KeyHandle> {
let (parent_hash_alg, parent_symmetric, policy_digests) = session_config(context, parent)?;

let policy_auth_session = context
.start_auth_session(
None,
None,
None,
SessionType::Policy,
Cipher::aes_128_cfb().try_into()?,
HashingAlgorithm::Sha256,
parent_symmetric.into(),
parent_hash_alg,
)?
.ok_or_else(|| Error::local_error(WrapperErrorKind::WrongValueFromTpm))?;

Expand Down Expand Up @@ -147,6 +209,13 @@ pub fn load_ak(
)
})?;

if !policy_digests.is_empty() {
ctx.policy_or(
PolicySession::try_from(policy_auth_session)?,
policy_digests,
)?
}

ctx.execute_with_session(Some(policy_auth_session), |ctx| {
ctx.load(parent, private, public)
})
Expand All @@ -171,15 +240,16 @@ pub fn create_ak<IKC: IntoKeyCustomization>(
key_customization: IKC,
) -> Result<CreateKeyResult> {
let ak_pub = create_ak_public(key_alg, hash_alg, sign_alg, key_customization)?;
let (parent_hash_alg, parent_symmetric, policy_digests) = session_config(context, parent)?;

let policy_auth_session = context
.start_auth_session(
None,
None,
None,
SessionType::Policy,
Cipher::aes_128_cfb().try_into()?,
HashingAlgorithm::Sha256,
parent_symmetric.into(),
parent_hash_alg,
)?
.ok_or_else(|| Error::local_error(WrapperErrorKind::WrongValueFromTpm))?;

Expand Down Expand Up @@ -212,6 +282,13 @@ pub fn create_ak<IKC: IntoKeyCustomization>(
)
})?;

if !policy_digests.is_empty() {
ctx.policy_or(
PolicySession::try_from(policy_auth_session)?,
policy_digests,
)?
};

ctx.execute_with_session(Some(policy_auth_session), |ctx| {
ctx.create(parent, ak_pub, ak_auth_value, None, None, None)
})
Expand Down
172 changes: 121 additions & 51 deletions tss-esapi/src/abstraction/ek.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ use crate::{
reserved_handles::{Hierarchy, NvAuth},
},
structures::{
Digest, EccParameter, EccPoint, EccScheme, KeyDerivationFunctionScheme, Public,
PublicBuilder, PublicEccParametersBuilder, PublicKeyRsa, PublicRsaParametersBuilder,
RsaExponent, RsaScheme, SymmetricDefinitionObject,
EccParameter, EccPoint, EccScheme, KeyDerivationFunctionScheme, Public, PublicBuilder,
PublicEccParametersBuilder, PublicKeyRsa, PublicRsaParametersBuilder, RsaExponent,
RsaScheme, SymmetricDefinitionObject,
},
Context, Error, Result, WrapperErrorKind,
};
Expand All @@ -32,8 +32,32 @@ 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;

// Source: TCG EK Credential Profile for TPM Family 2.0; Level 0 Version 2.5 Revision 2
// Section B.3 and B.4
const AUTHPOLICY_A_SHA256: [u8; 32] = [
0x83, 0x71, 0x97, 0x67, 0x44, 0x84, 0xb3, 0xf8, 0x1a, 0x90, 0xcc, 0x8d, 0x46, 0xa5, 0xd7, 0x24,
0xfd, 0x52, 0xd7, 0x6e, 0x06, 0x52, 0x0b, 0x64, 0xf2, 0xa1, 0xda, 0x1b, 0x33, 0x14, 0x69, 0xaa,
];
const AUTHPOLICY_B_SHA384: [u8; 48] = [
0xb2, 0x6e, 0x7d, 0x28, 0xd1, 0x1a, 0x50, 0xbc, 0x53, 0xd8, 0x82, 0xbc, 0xf5, 0xfd, 0x3a, 0x1a,
0x07, 0x41, 0x48, 0xbb, 0x35, 0xd3, 0xb4, 0xe4, 0xcb, 0x1c, 0x0a, 0xd9, 0xbd, 0xe4, 0x19, 0xca,
0xcb, 0x47, 0xba, 0x09, 0x69, 0x96, 0x46, 0x15, 0x0f, 0x9f, 0xc0, 0x00, 0xf3, 0xf8, 0x0e, 0x12,
];
const AUTHPOLICY_B_SHA512: [u8; 64] = [
0xb8, 0x22, 0x1c, 0xa6, 0x9e, 0x85, 0x50, 0xa4, 0x91, 0x4d, 0xe3, 0xfa, 0xa6, 0xa1, 0x8c, 0x07,
0x2c, 0xc0, 0x12, 0x08, 0x07, 0x3a, 0x92, 0x8d, 0x5d, 0x66, 0xd5, 0x9e, 0xf7, 0x9e, 0x49, 0xa4,
0x29, 0xc4, 0x1a, 0x6b, 0x26, 0x95, 0x71, 0xd5, 0x7e, 0xdb, 0x25, 0xfb, 0xdb, 0x18, 0x38, 0x42,
0x56, 0x08, 0xb4, 0x13, 0xcd, 0x61, 0x6a, 0x5f, 0x6d, 0xb5, 0xb6, 0x07, 0x1a, 0xf9, 0x9b, 0xea,
];
const AUTHPOLICY_B_SM3_256: [u8; 32] = [
0x16, 0x78, 0x60, 0xa3, 0x5f, 0x2c, 0x5c, 0x35, 0x67, 0xf9, 0xc9, 0x27, 0xac, 0x56, 0xc0, 0x32,
0xf3, 0xb3, 0xa6, 0x46, 0x2f, 0x8d, 0x03, 0x79, 0x98, 0xe7, 0xa1, 0x0f, 0x77, 0xfa, 0x45, 0x4a,
];

/// Get the [`Public`] representing a default Endorsement Key
///
/// **Note**: This only works for key algorithms specified in TCG EK Credential Profile for TPM Family 2.0.
///
/// 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>(
Expand All @@ -42,12 +66,19 @@ pub fn create_ek_public_from_default_template<IKC: IntoKeyCustomization>(
) -> Result<Public> {
let key_customization = key_customization.into_key_customization();

// user_with_auth is not set for the lower profiles (RSA 20248 and ECC P256)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit:

Suggested change
// user_with_auth is not set for the lower profiles (RSA 20248 and ECC P256)
// user_with_auth is not set for the lower profiles (RSA 2048 and ECC P256)

let user_with_auth = !matches!(
alg,
AsymmetricAlgorithmSelection::Rsa(RsaKeyBits::Rsa2048)
| AsymmetricAlgorithmSelection::Ecc(EccCurve::NistP256)
);

let obj_attrs_builder = ObjectAttributesBuilder::new()
.with_fixed_tpm(true)
.with_st_clear(false)
.with_fixed_parent(true)
.with_sensitive_data_origin(true)
.with_user_with_auth(false)
.with_user_with_auth(user_with_auth)
.with_admin_with_policy(true)
.with_no_da(false)
.with_encrypted_duplication(false)
Expand All @@ -62,54 +93,93 @@ pub fn create_ek_public_from_default_template<IKC: IntoKeyCustomization>(
}
.build()?;

// TPM2_PolicySecret(TPM_RH_ENDORSEMENT)
// With 32 null-bytes attached, because of the type of with_auth_policy
let authpolicy: [u8; 64] = [
0x83, 0x71, 0x97, 0x67, 0x44, 0x84, 0xb3, 0xf8, 0x1a, 0x90, 0xcc, 0x8d, 0x46, 0xa5, 0xd7,
0x24, 0xfd, 0x52, 0xd7, 0x6e, 0x06, 0x52, 0x0b, 0x64, 0xf2, 0xa1, 0xda, 0x1b, 0x33, 0x14,
0x69, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00,
];

let key_builder = match alg {
AsymmetricAlgorithmSelection::Rsa(key_bits) => PublicBuilder::new()
.with_public_algorithm(PublicAlgorithm::Rsa)
.with_name_hashing_algorithm(HashingAlgorithm::Sha256)
.with_object_attributes(obj_attrs)
.with_auth_policy(Digest::try_from(authpolicy[0..32].to_vec())?)
.with_rsa_parameters(
PublicRsaParametersBuilder::new()
.with_symmetric(SymmetricDefinitionObject::AES_128_CFB)
.with_scheme(RsaScheme::Null)
.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)),
AsymmetricAlgorithmSelection::Ecc(ecc_curve) => PublicBuilder::new()
.with_public_algorithm(PublicAlgorithm::Ecc)
.with_name_hashing_algorithm(HashingAlgorithm::Sha256)
.with_object_attributes(obj_attrs)
.with_auth_policy(Digest::try_from(authpolicy[0..32].to_vec())?)
.with_ecc_parameters(
PublicEccParametersBuilder::new()
.with_symmetric(SymmetricDefinitionObject::AES_128_CFB)
.with_ecc_scheme(EccScheme::Null)
.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())
.with_restricted(obj_attrs.decrypt())
.build()?,
)
.with_ecc_unique_identifier(EccPoint::new(
EccParameter::try_from(vec![0u8; 32])?,
EccParameter::try_from(vec![0u8; 32])?,
)),
AsymmetricAlgorithmSelection::Rsa(key_bits) => {
let (hash_alg, authpolicy, symmetric, unique) = match key_bits {
RsaKeyBits::Rsa2048 => (
HashingAlgorithm::Sha256,
AUTHPOLICY_A_SHA256.into(),
SymmetricDefinitionObject::AES_128_CFB,
PublicKeyRsa::new_empty_with_size(RsaKeyBits::Rsa2048),
),
RsaKeyBits::Rsa3072 | RsaKeyBits::Rsa4096 => (
HashingAlgorithm::Sha384,
AUTHPOLICY_B_SHA384.into(),
SymmetricDefinitionObject::AES_256_CFB,
PublicKeyRsa::new_empty(),
),
// Other key sizes are not supported in the spec, so return a error
_ => return Err(Error::local_error(WrapperErrorKind::UnsupportedParam)),
};

PublicBuilder::new()
.with_public_algorithm(PublicAlgorithm::Rsa)
.with_name_hashing_algorithm(hash_alg)
.with_object_attributes(obj_attrs)
.with_auth_policy(authpolicy)
.with_rsa_parameters(
PublicRsaParametersBuilder::new()
.with_symmetric(symmetric)
.with_scheme(RsaScheme::Null)
.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(unique)
}
AsymmetricAlgorithmSelection::Ecc(ecc_curve) => {
let (hash_alg, authpolicy, symmetric, xy_size) = match ecc_curve {
EccCurve::NistP256 => (
HashingAlgorithm::Sha256,
AUTHPOLICY_A_SHA256.into(),
SymmetricDefinitionObject::AES_128_CFB,
32,
),
EccCurve::NistP384 => (
HashingAlgorithm::Sha384,
AUTHPOLICY_B_SHA384.into(),
SymmetricDefinitionObject::AES_256_CFB,
0,
),
EccCurve::NistP521 => (
HashingAlgorithm::Sha512,
AUTHPOLICY_B_SHA512.into(),
SymmetricDefinitionObject::AES_256_CFB,
0,
),
EccCurve::Sm2P256 => (
HashingAlgorithm::Sm3_256,
AUTHPOLICY_B_SM3_256.into(),
SymmetricDefinitionObject::SM4_128_CFB,
0,
),
// Other curves are not supported in the spec, so return a error
_ => return Err(Error::local_error(WrapperErrorKind::UnsupportedParam)),
};
PublicBuilder::new()
.with_public_algorithm(PublicAlgorithm::Ecc)
.with_name_hashing_algorithm(hash_alg)
.with_object_attributes(obj_attrs)
.with_auth_policy(authpolicy)
.with_ecc_parameters(
PublicEccParametersBuilder::new()
.with_symmetric(symmetric)
.with_ecc_scheme(EccScheme::Null)
.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())
.with_restricted(obj_attrs.decrypt())
.build()?,
)
.with_ecc_unique_identifier(EccPoint::new(
EccParameter::try_from(vec![0u8; xy_size])?,
EccParameter::try_from(vec![0u8; xy_size])?,
))
}
};

let key_builder = if let Some(ref k) = key_customization {
Expand Down
4 changes: 4 additions & 0 deletions tss-esapi/src/structures/buffers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,10 @@ pub mod public_key_rsa {
RsaKeyBits::Rsa4096 => PublicKeyRsa(vec![0u8; 512].into()),
}
}

pub fn new_empty() -> Self {
PublicKeyRsa(vec![0u8; 0].into())
}
}

impl TryFrom<PublicKeyRsa> for [u8; 128] {
Expand Down
5 changes: 5 additions & 0 deletions tss-esapi/src/structures/parameters.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@ impl SymmetricCipherParameters {
symmetric_definition_object,
}
}

/// Returns the [SymmetricDefinitionObject].
pub const fn symmetric_definition_object(&self) -> SymmetricDefinitionObject {
self.symmetric_definition_object
}
}

impl TryFrom<TPMS_SYMCIPHER_PARMS> for SymmetricCipherParameters {
Expand Down
Loading
Loading