Skip to content

Commit 2176c29

Browse files
committed
ek,ak abstraction: align with TCG EK Credential Profile
Signed-off-by: Thore Sommer <mail@thson.de>
1 parent 2baa4d3 commit 2176c29

File tree

4 files changed

+281
-78
lines changed

4 files changed

+281
-78
lines changed

tss-esapi/src/abstraction/ak.rs

Lines changed: 88 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,7 @@
22
// SPDX-License-Identifier: Apache-2.0
33

44
use crate::{
5-
abstraction::{
6-
cipher::Cipher, AsymmetricAlgorithmSelection, IntoKeyCustomization, KeyCustomization,
7-
},
5+
abstraction::{AsymmetricAlgorithmSelection, IntoKeyCustomization, KeyCustomization},
86
attributes::{ObjectAttributesBuilder, SessionAttributesBuilder},
97
constants::{AlgorithmIdentifier, SessionType},
108
handles::{AuthHandle, KeyHandle, SessionHandle},
@@ -16,13 +14,46 @@ use crate::{
1614
session_handles::PolicySession,
1715
},
1816
structures::{
19-
Auth, CreateKeyResult, EccPoint, EccScheme, KeyDerivationFunctionScheme, Private, Public,
20-
PublicBuilder, PublicEccParametersBuilder, PublicKeyRsa, PublicRsaParametersBuilder,
21-
RsaExponent, RsaScheme, SymmetricDefinitionObject,
17+
Auth, CreateKeyResult, DigestList, EccPoint, EccScheme, KeyDerivationFunctionScheme,
18+
Private, Public, PublicBuilder, PublicEccParametersBuilder, PublicKeyRsa,
19+
PublicRsaParametersBuilder, RsaExponent, RsaScheme, SymmetricDefinitionObject,
2220
},
2321
Context, Error, Result, WrapperErrorKind,
2422
};
25-
use std::convert::{TryFrom, TryInto};
23+
use std::convert::TryFrom;
24+
25+
// Source: TCG EK Credential Profile for TPM Family 2.0; Level 0 Version 2.5 Revision 2
26+
// Section B.6
27+
const POLICY_A_SHA384: [u8; 48] = [
28+
0x8b, 0xbf, 0x22, 0x66, 0x53, 0x7c, 0x17, 0x1c, 0xb5, 0x6e, 0x40, 0x3c, 0x4d, 0xc1, 0xd4, 0xb6,
29+
0x4f, 0x43, 0x26, 0x11, 0xdc, 0x38, 0x6e, 0x6f, 0x53, 0x20, 0x50, 0xc3, 0x27, 0x8c, 0x93, 0x0e,
30+
0x14, 0x3e, 0x8b, 0xb1, 0x13, 0x38, 0x24, 0xcc, 0xb4, 0x31, 0x05, 0x38, 0x71, 0xc6, 0xdb, 0x53,
31+
];
32+
const POLICY_A_SHA512: [u8; 64] = [
33+
0x1e, 0x3b, 0x76, 0x50, 0x2c, 0x8a, 0x14, 0x25, 0xaa, 0x0b, 0x7b, 0x3f, 0xc6, 0x46, 0xa1, 0xb0,
34+
0xfa, 0xe0, 0x63, 0xb0, 0x3b, 0x53, 0x68, 0xf9, 0xc4, 0xcd, 0xde, 0xca, 0xff, 0x08, 0x91, 0xdd,
35+
0x68, 0x2b, 0xac, 0x1a, 0x85, 0xd4, 0xd8, 0x32, 0xb7, 0x81, 0xea, 0x45, 0x19, 0x15, 0xde, 0x5f,
36+
0xc5, 0xbf, 0x0d, 0xc4, 0xa1, 0x91, 0x7c, 0xd4, 0x2f, 0xa0, 0x41, 0xe3, 0xf9, 0x98, 0xe0, 0xee,
37+
];
38+
const POLICY_A_SM3_256: [u8; 32] = [
39+
0xc6, 0x7f, 0x7d, 0x35, 0xf6, 0x6f, 0x3b, 0xec, 0x13, 0xc8, 0x9f, 0xe8, 0x98, 0x92, 0x1c, 0x65,
40+
0x1b, 0x0c, 0xb5, 0xa3, 0x8a, 0x92, 0x69, 0x0a, 0x62, 0xa4, 0x3c, 0x00, 0x12, 0xe4, 0xfb, 0x8b,
41+
];
42+
const POLICY_C_SHA384: [u8; 48] = [
43+
0xd6, 0x03, 0x2c, 0xe6, 0x1f, 0x2f, 0xb3, 0xc2, 0x40, 0xeb, 0x3c, 0xf6, 0xa3, 0x32, 0x37, 0xef,
44+
0x2b, 0x6a, 0x16, 0xf4, 0x29, 0x3c, 0x22, 0xb4, 0x55, 0xe2, 0x61, 0xcf, 0xfd, 0x21, 0x7a, 0xd5,
45+
0xb4, 0x94, 0x7c, 0x2d, 0x73, 0xe6, 0x30, 0x05, 0xee, 0xd2, 0xdc, 0x2b, 0x35, 0x93, 0xd1, 0x65,
46+
];
47+
const POLICY_C_SHA512: [u8; 64] = [
48+
0x58, 0x9e, 0xe1, 0xe1, 0x46, 0x54, 0x47, 0x16, 0xe8, 0xde, 0xaf, 0xe6, 0xdb, 0x24, 0x7b, 0x01,
49+
0xb8, 0x1e, 0x9f, 0x9c, 0x7d, 0xd1, 0x6b, 0x81, 0x4a, 0xa1, 0x59, 0x13, 0x87, 0x49, 0x10, 0x5f,
50+
0xba, 0x53, 0x88, 0xdd, 0x1d, 0xea, 0x70, 0x2f, 0x35, 0x24, 0x0c, 0x18, 0x49, 0x33, 0x12, 0x1e,
51+
0x2c, 0x61, 0xb8, 0xf5, 0x0d, 0x3e, 0xf9, 0x13, 0x93, 0xa4, 0x9a, 0x38, 0xc3, 0xf7, 0x3f, 0xc8,
52+
];
53+
const POLICY_C_SM3_256: [u8; 32] = [
54+
0x2d, 0x4e, 0x81, 0x57, 0x8c, 0x35, 0x31, 0xd9, 0xbd, 0x1c, 0xdd, 0x7d, 0x02, 0xba, 0x29, 0x8d,
55+
0x56, 0x99, 0xa3, 0xe3, 0x9f, 0xc3, 0x55, 0x1b, 0xfe, 0xff, 0xcf, 0x13, 0x2b, 0x49, 0xe1, 0x1d,
56+
];
2657

2758
fn create_ak_public<IKC: IntoKeyCustomization>(
2859
key_alg: AsymmetricAlgorithmSelection,
@@ -99,6 +130,35 @@ fn create_ak_public<IKC: IntoKeyCustomization>(
99130
key_builder.build()
100131
}
101132

133+
// extracts the hashing and sysmmetric algorithm from parent and constructs the correct DigestList for OR policy
134+
fn session_config(
135+
context: &mut Context,
136+
parent: KeyHandle,
137+
) -> Result<(HashingAlgorithm, SymmetricDefinitionObject, DigestList)> {
138+
let parent_hash_alg = context.read_public(parent)?.0.name_hashing_algorithm();
139+
let parent_symmetric = context.read_public(parent)?.0.symmetric_algorithm()?;
140+
141+
let mut policy_digests = DigestList::new();
142+
143+
match parent_hash_alg {
144+
HashingAlgorithm::Sha384 => {
145+
policy_digests.add(POLICY_A_SHA384.into())?;
146+
policy_digests.add(POLICY_C_SHA384.into())?
147+
}
148+
HashingAlgorithm::Sha512 => {
149+
policy_digests.add(POLICY_A_SHA512.into())?;
150+
policy_digests.add(POLICY_C_SHA512.into())?
151+
}
152+
HashingAlgorithm::Sm3_256 => {
153+
policy_digests.add(POLICY_A_SM3_256.into())?;
154+
policy_digests.add(POLICY_C_SM3_256.into())?
155+
}
156+
_ => (),
157+
};
158+
159+
Ok((parent_hash_alg, parent_symmetric, policy_digests))
160+
}
161+
102162
/// This loads an Attestation Key previously generated under the Endorsement hierarchy
103163
pub fn load_ak(
104164
context: &mut Context,
@@ -107,14 +167,16 @@ pub fn load_ak(
107167
private: Private,
108168
public: Public,
109169
) -> Result<KeyHandle> {
170+
let (parent_hash_alg, parent_symmetric, policy_digests) = session_config(context, parent)?;
171+
110172
let policy_auth_session = context
111173
.start_auth_session(
112174
None,
113175
None,
114176
None,
115177
SessionType::Policy,
116-
Cipher::aes_128_cfb().try_into()?,
117-
HashingAlgorithm::Sha256,
178+
parent_symmetric.into(),
179+
parent_hash_alg,
118180
)?
119181
.ok_or_else(|| Error::local_error(WrapperErrorKind::WrongValueFromTpm))?;
120182

@@ -147,6 +209,13 @@ pub fn load_ak(
147209
)
148210
})?;
149211

212+
if !policy_digests.is_empty() {
213+
ctx.policy_or(
214+
PolicySession::try_from(policy_auth_session)?,
215+
policy_digests,
216+
)?
217+
}
218+
150219
ctx.execute_with_session(Some(policy_auth_session), |ctx| {
151220
ctx.load(parent, private, public)
152221
})
@@ -171,15 +240,16 @@ pub fn create_ak<IKC: IntoKeyCustomization>(
171240
key_customization: IKC,
172241
) -> Result<CreateKeyResult> {
173242
let ak_pub = create_ak_public(key_alg, hash_alg, sign_alg, key_customization)?;
243+
let (parent_hash_alg, parent_symmetric, policy_digests) = session_config(context, parent)?;
174244

175245
let policy_auth_session = context
176246
.start_auth_session(
177247
None,
178248
None,
179249
None,
180250
SessionType::Policy,
181-
Cipher::aes_128_cfb().try_into()?,
182-
HashingAlgorithm::Sha256,
251+
parent_symmetric.into(),
252+
parent_hash_alg,
183253
)?
184254
.ok_or_else(|| Error::local_error(WrapperErrorKind::WrongValueFromTpm))?;
185255

@@ -212,6 +282,13 @@ pub fn create_ak<IKC: IntoKeyCustomization>(
212282
)
213283
})?;
214284

285+
if !policy_digests.is_empty() {
286+
ctx.policy_or(
287+
PolicySession::try_from(policy_auth_session)?,
288+
policy_digests,
289+
)?
290+
};
291+
215292
ctx.execute_with_session(Some(policy_auth_session), |ctx| {
216293
ctx.create(parent, ak_pub, ak_auth_value, None, None, None)
217294
})

tss-esapi/src/abstraction/ek.rs

Lines changed: 121 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,9 @@ use crate::{
1212
reserved_handles::{Hierarchy, NvAuth},
1313
},
1414
structures::{
15-
Digest, EccParameter, EccPoint, EccScheme, KeyDerivationFunctionScheme, Public,
16-
PublicBuilder, PublicEccParametersBuilder, PublicKeyRsa, PublicRsaParametersBuilder,
17-
RsaExponent, RsaScheme, SymmetricDefinitionObject,
15+
EccParameter, EccPoint, EccScheme, KeyDerivationFunctionScheme, Public, PublicBuilder,
16+
PublicEccParametersBuilder, PublicKeyRsa, PublicRsaParametersBuilder, RsaExponent,
17+
RsaScheme, SymmetricDefinitionObject,
1818
},
1919
Context, Error, Result, WrapperErrorKind,
2020
};
@@ -32,8 +32,32 @@ const ECC_P256_SM2_EK_CERTIFICATE_NV_INDEX: u32 = 0x01c0001a;
3232
const RSA_3072_EK_CERTIFICATE_NV_INDEX: u32 = 0x01c0001c;
3333
const RSA_4096_EK_CERTIFICATE_NV_INDEX: u32 = 0x01c0001e;
3434

35+
// Source: TCG EK Credential Profile for TPM Family 2.0; Level 0 Version 2.5 Revision 2
36+
// Section B.3 and B.4
37+
const AUTHPOLICY_A_SHA256: [u8; 32] = [
38+
0x83, 0x71, 0x97, 0x67, 0x44, 0x84, 0xb3, 0xf8, 0x1a, 0x90, 0xcc, 0x8d, 0x46, 0xa5, 0xd7, 0x24,
39+
0xfd, 0x52, 0xd7, 0x6e, 0x06, 0x52, 0x0b, 0x64, 0xf2, 0xa1, 0xda, 0x1b, 0x33, 0x14, 0x69, 0xaa,
40+
];
41+
const AUTHPOLICY_B_SHA384: [u8; 48] = [
42+
0xb2, 0x6e, 0x7d, 0x28, 0xd1, 0x1a, 0x50, 0xbc, 0x53, 0xd8, 0x82, 0xbc, 0xf5, 0xfd, 0x3a, 0x1a,
43+
0x07, 0x41, 0x48, 0xbb, 0x35, 0xd3, 0xb4, 0xe4, 0xcb, 0x1c, 0x0a, 0xd9, 0xbd, 0xe4, 0x19, 0xca,
44+
0xcb, 0x47, 0xba, 0x09, 0x69, 0x96, 0x46, 0x15, 0x0f, 0x9f, 0xc0, 0x00, 0xf3, 0xf8, 0x0e, 0x12,
45+
];
46+
const AUTHPOLICY_B_SHA512: [u8; 64] = [
47+
0xb8, 0x22, 0x1c, 0xa6, 0x9e, 0x85, 0x50, 0xa4, 0x91, 0x4d, 0xe3, 0xfa, 0xa6, 0xa1, 0x8c, 0x07,
48+
0x2c, 0xc0, 0x12, 0x08, 0x07, 0x3a, 0x92, 0x8d, 0x5d, 0x66, 0xd5, 0x9e, 0xf7, 0x9e, 0x49, 0xa4,
49+
0x29, 0xc4, 0x1a, 0x6b, 0x26, 0x95, 0x71, 0xd5, 0x7e, 0xdb, 0x25, 0xfb, 0xdb, 0x18, 0x38, 0x42,
50+
0x56, 0x08, 0xb4, 0x13, 0xcd, 0x61, 0x6a, 0x5f, 0x6d, 0xb5, 0xb6, 0x07, 0x1a, 0xf9, 0x9b, 0xea,
51+
];
52+
const AUTHPOLICY_B_SM3_256: [u8; 32] = [
53+
0x16, 0x78, 0x60, 0xa3, 0x5f, 0x2c, 0x5c, 0x35, 0x67, 0xf9, 0xc9, 0x27, 0xac, 0x56, 0xc0, 0x32,
54+
0xf3, 0xb3, 0xa6, 0x46, 0x2f, 0x8d, 0x03, 0x79, 0x98, 0xe7, 0xa1, 0x0f, 0x77, 0xfa, 0x45, 0x4a,
55+
];
56+
3557
/// Get the [`Public`] representing a default Endorsement Key
3658
///
59+
/// **Note**: This only works for key algorithms specified in TCG EK Credential Profile for TPM Family 2.0.
60+
///
3761
/// Source: TCG EK Credential Profile for TPM Family 2.0; Level 0 Version 2.3 Revision 2
3862
/// Appendix B.3.3 and B.3.4
3963
pub fn create_ek_public_from_default_template<IKC: IntoKeyCustomization>(
@@ -42,12 +66,19 @@ pub fn create_ek_public_from_default_template<IKC: IntoKeyCustomization>(
4266
) -> Result<Public> {
4367
let key_customization = key_customization.into_key_customization();
4468

69+
// user_with_auth is not set for the lower profiles (RSA 20248 and ECC P256)
70+
let user_with_auth = !matches!(
71+
alg,
72+
AsymmetricAlgorithmSelection::Rsa(RsaKeyBits::Rsa2048)
73+
| AsymmetricAlgorithmSelection::Ecc(EccCurve::NistP256)
74+
);
75+
4576
let obj_attrs_builder = ObjectAttributesBuilder::new()
4677
.with_fixed_tpm(true)
4778
.with_st_clear(false)
4879
.with_fixed_parent(true)
4980
.with_sensitive_data_origin(true)
50-
.with_user_with_auth(false)
81+
.with_user_with_auth(user_with_auth)
5182
.with_admin_with_policy(true)
5283
.with_no_da(false)
5384
.with_encrypted_duplication(false)
@@ -62,54 +93,93 @@ pub fn create_ek_public_from_default_template<IKC: IntoKeyCustomization>(
6293
}
6394
.build()?;
6495

65-
// TPM2_PolicySecret(TPM_RH_ENDORSEMENT)
66-
// With 32 null-bytes attached, because of the type of with_auth_policy
67-
let authpolicy: [u8; 64] = [
68-
0x83, 0x71, 0x97, 0x67, 0x44, 0x84, 0xb3, 0xf8, 0x1a, 0x90, 0xcc, 0x8d, 0x46, 0xa5, 0xd7,
69-
0x24, 0xfd, 0x52, 0xd7, 0x6e, 0x06, 0x52, 0x0b, 0x64, 0xf2, 0xa1, 0xda, 0x1b, 0x33, 0x14,
70-
0x69, 0xaa, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
71-
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
72-
0x00, 0x00, 0x00, 0x00,
73-
];
74-
7596
let key_builder = match alg {
76-
AsymmetricAlgorithmSelection::Rsa(key_bits) => PublicBuilder::new()
77-
.with_public_algorithm(PublicAlgorithm::Rsa)
78-
.with_name_hashing_algorithm(HashingAlgorithm::Sha256)
79-
.with_object_attributes(obj_attrs)
80-
.with_auth_policy(Digest::try_from(authpolicy[0..32].to_vec())?)
81-
.with_rsa_parameters(
82-
PublicRsaParametersBuilder::new()
83-
.with_symmetric(SymmetricDefinitionObject::AES_128_CFB)
84-
.with_scheme(RsaScheme::Null)
85-
.with_key_bits(key_bits)
86-
.with_exponent(RsaExponent::default())
87-
.with_is_signing_key(obj_attrs.sign_encrypt())
88-
.with_is_decryption_key(obj_attrs.decrypt())
89-
.with_restricted(obj_attrs.decrypt())
90-
.build()?,
91-
)
92-
.with_rsa_unique_identifier(PublicKeyRsa::new_empty_with_size(RsaKeyBits::Rsa2048)),
93-
AsymmetricAlgorithmSelection::Ecc(ecc_curve) => PublicBuilder::new()
94-
.with_public_algorithm(PublicAlgorithm::Ecc)
95-
.with_name_hashing_algorithm(HashingAlgorithm::Sha256)
96-
.with_object_attributes(obj_attrs)
97-
.with_auth_policy(Digest::try_from(authpolicy[0..32].to_vec())?)
98-
.with_ecc_parameters(
99-
PublicEccParametersBuilder::new()
100-
.with_symmetric(SymmetricDefinitionObject::AES_128_CFB)
101-
.with_ecc_scheme(EccScheme::Null)
102-
.with_curve(ecc_curve)
103-
.with_key_derivation_function_scheme(KeyDerivationFunctionScheme::Null)
104-
.with_is_signing_key(obj_attrs.sign_encrypt())
105-
.with_is_decryption_key(obj_attrs.decrypt())
106-
.with_restricted(obj_attrs.decrypt())
107-
.build()?,
108-
)
109-
.with_ecc_unique_identifier(EccPoint::new(
110-
EccParameter::try_from(vec![0u8; 32])?,
111-
EccParameter::try_from(vec![0u8; 32])?,
112-
)),
97+
AsymmetricAlgorithmSelection::Rsa(key_bits) => {
98+
let (hash_alg, authpolicy, symmetric, unique) = match key_bits {
99+
RsaKeyBits::Rsa2048 => (
100+
HashingAlgorithm::Sha256,
101+
AUTHPOLICY_A_SHA256.into(),
102+
SymmetricDefinitionObject::AES_128_CFB,
103+
PublicKeyRsa::new_empty_with_size(RsaKeyBits::Rsa2048),
104+
),
105+
RsaKeyBits::Rsa3072 | RsaKeyBits::Rsa4096 => (
106+
HashingAlgorithm::Sha384,
107+
AUTHPOLICY_B_SHA384.into(),
108+
SymmetricDefinitionObject::AES_256_CFB,
109+
PublicKeyRsa::new_empty(),
110+
),
111+
// Other key sizes are not supported in the spec, so return a error
112+
_ => return Err(Error::local_error(WrapperErrorKind::UnsupportedParam)),
113+
};
114+
115+
PublicBuilder::new()
116+
.with_public_algorithm(PublicAlgorithm::Rsa)
117+
.with_name_hashing_algorithm(hash_alg)
118+
.with_object_attributes(obj_attrs)
119+
.with_auth_policy(authpolicy)
120+
.with_rsa_parameters(
121+
PublicRsaParametersBuilder::new()
122+
.with_symmetric(symmetric)
123+
.with_scheme(RsaScheme::Null)
124+
.with_key_bits(key_bits)
125+
.with_exponent(RsaExponent::default())
126+
.with_is_signing_key(obj_attrs.sign_encrypt())
127+
.with_is_decryption_key(obj_attrs.decrypt())
128+
.with_restricted(obj_attrs.decrypt())
129+
.build()?,
130+
)
131+
.with_rsa_unique_identifier(unique)
132+
}
133+
AsymmetricAlgorithmSelection::Ecc(ecc_curve) => {
134+
let (hash_alg, authpolicy, symmetric, xy_size) = match ecc_curve {
135+
EccCurve::NistP256 => (
136+
HashingAlgorithm::Sha256,
137+
AUTHPOLICY_A_SHA256.into(),
138+
SymmetricDefinitionObject::AES_128_CFB,
139+
32,
140+
),
141+
EccCurve::NistP384 => (
142+
HashingAlgorithm::Sha384,
143+
AUTHPOLICY_B_SHA384.into(),
144+
SymmetricDefinitionObject::AES_256_CFB,
145+
0,
146+
),
147+
EccCurve::NistP521 => (
148+
HashingAlgorithm::Sha512,
149+
AUTHPOLICY_B_SHA512.into(),
150+
SymmetricDefinitionObject::AES_256_CFB,
151+
0,
152+
),
153+
EccCurve::Sm2P256 => (
154+
HashingAlgorithm::Sm3_256,
155+
AUTHPOLICY_B_SM3_256.into(),
156+
SymmetricDefinitionObject::SM4_128_CFB,
157+
0,
158+
),
159+
// Other curves are not supported in the spec, so return a error
160+
_ => return Err(Error::local_error(WrapperErrorKind::UnsupportedParam)),
161+
};
162+
PublicBuilder::new()
163+
.with_public_algorithm(PublicAlgorithm::Ecc)
164+
.with_name_hashing_algorithm(hash_alg)
165+
.with_object_attributes(obj_attrs)
166+
.with_auth_policy(authpolicy)
167+
.with_ecc_parameters(
168+
PublicEccParametersBuilder::new()
169+
.with_symmetric(symmetric)
170+
.with_ecc_scheme(EccScheme::Null)
171+
.with_curve(ecc_curve)
172+
.with_key_derivation_function_scheme(KeyDerivationFunctionScheme::Null)
173+
.with_is_signing_key(obj_attrs.sign_encrypt())
174+
.with_is_decryption_key(obj_attrs.decrypt())
175+
.with_restricted(obj_attrs.decrypt())
176+
.build()?,
177+
)
178+
.with_ecc_unique_identifier(EccPoint::new(
179+
EccParameter::try_from(vec![0u8; xy_size])?,
180+
EccParameter::try_from(vec![0u8; xy_size])?,
181+
))
182+
}
113183
};
114184

115185
let key_builder = if let Some(ref k) = key_customization {

0 commit comments

Comments
 (0)