Skip to content

Commit db71335

Browse files
committed
ek, ak abstractions: allow to specficy exact key type
This adds support other keys than RSA2048 and ECC Nist P256. Signed-off-by: Thore Sommer <[email protected]>
1 parent 1e04007 commit db71335

File tree

7 files changed

+157
-56
lines changed

7 files changed

+157
-56
lines changed

tss-esapi/src/abstraction/ak.rs

Lines changed: 12 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,9 @@ use crate::{
88
handles::{AuthHandle, KeyHandle, SessionHandle},
99
interface_types::{
1010
algorithm::{
11-
AsymmetricAlgorithm, EccSchemeAlgorithm, HashingAlgorithm, PublicAlgorithm,
11+
AsymmetricAlgorithmSelection, EccSchemeAlgorithm, HashingAlgorithm, PublicAlgorithm,
1212
RsaSchemeAlgorithm, SignatureSchemeAlgorithm,
1313
},
14-
ecc::EccCurve,
15-
key_bits::RsaKeyBits,
1614
session_handles::PolicySession,
1715
},
1816
structures::{
@@ -26,7 +24,7 @@ use log::error;
2624
use std::convert::{TryFrom, TryInto};
2725

2826
fn create_ak_public<IKC: IntoKeyCustomization>(
29-
key_alg: AsymmetricAlgorithm,
27+
key_alg: AsymmetricAlgorithmSelection,
3028
hash_alg: HashingAlgorithm,
3129
sign_alg: SignatureSchemeAlgorithm,
3230
key_customization: IKC,
@@ -50,7 +48,9 @@ fn create_ak_public<IKC: IntoKeyCustomization>(
5048
.build()?;
5149

5250
let key_builder = match key_alg {
53-
AsymmetricAlgorithm::Rsa => PublicBuilder::new()
51+
AsymmetricAlgorithmSelection::Rsa2048
52+
| AsymmetricAlgorithmSelection::Rsa3072
53+
| AsymmetricAlgorithmSelection::Rsa4096 => PublicBuilder::new()
5454
.with_public_algorithm(PublicAlgorithm::Rsa)
5555
.with_name_hashing_algorithm(hash_alg)
5656
.with_object_attributes(obj_attrs)
@@ -60,15 +60,18 @@ fn create_ak_public<IKC: IntoKeyCustomization>(
6060
RsaSchemeAlgorithm::try_from(AlgorithmIdentifier::from(sign_alg))?,
6161
Some(hash_alg),
6262
)?)
63-
.with_key_bits(RsaKeyBits::Rsa2048)
63+
.with_key_bits(key_alg.try_into()?)
6464
.with_exponent(RsaExponent::default())
6565
.with_is_signing_key(obj_attrs.sign_encrypt())
6666
.with_is_decryption_key(obj_attrs.decrypt())
6767
.with_restricted(obj_attrs.restricted())
6868
.build()?,
6969
)
7070
.with_rsa_unique_identifier(PublicKeyRsa::default()),
71-
AsymmetricAlgorithm::Ecc => PublicBuilder::new()
71+
AsymmetricAlgorithmSelection::EccP256
72+
| AsymmetricAlgorithmSelection::EccP384
73+
| AsymmetricAlgorithmSelection::EccP521
74+
| AsymmetricAlgorithmSelection::EccP256Sm2 => PublicBuilder::new()
7275
.with_public_algorithm(PublicAlgorithm::Ecc)
7376
.with_name_hashing_algorithm(hash_alg)
7477
.with_object_attributes(obj_attrs)
@@ -80,14 +83,10 @@ fn create_ak_public<IKC: IntoKeyCustomization>(
8083
Some(hash_alg),
8184
Some(0),
8285
)?)
83-
.with_curve(EccCurve::NistP192)
86+
.with_curve(key_alg.try_into()?)
8487
.with_key_derivation_function_scheme(KeyDerivationFunctionScheme::Null)
8588
.build()?,
8689
),
87-
AsymmetricAlgorithm::Null => {
88-
// TODO: Figure out what to with Null.
89-
return Err(Error::local_error(WrapperErrorKind::UnsupportedParam));
90-
}
9190
};
9291

9392
let key_builder = if let Some(ref k) = key_customization {
@@ -164,7 +163,7 @@ pub fn create_ak<IKC: IntoKeyCustomization>(
164163
ak_auth_value: Option<Auth>,
165164
key_customization: IKC,
166165
) -> Result<CreateKeyResult> {
167-
let key_alg = AsymmetricAlgorithm::try_from(sign_alg).map_err(|e| {
166+
let key_alg = AsymmetricAlgorithmSelection::try_from(sign_alg).map_err(|e| {
168167
// sign_alg is either HMAC or Null.
169168
error!("Could not retrieve asymmetric algorithm for provided signature scheme");
170169
e

tss-esapi/src/abstraction/ek.rs

Lines changed: 33 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,7 @@ use crate::{
66
attributes::ObjectAttributesBuilder,
77
handles::{KeyHandle, NvIndexTpmHandle, TpmHandle},
88
interface_types::{
9-
algorithm::{AsymmetricAlgorithm, HashingAlgorithm, PublicAlgorithm},
10-
ecc::EccCurve,
9+
algorithm::{AsymmetricAlgorithmSelection, HashingAlgorithm, PublicAlgorithm},
1110
key_bits::RsaKeyBits,
1211
resource_handles::{Hierarchy, NvAuth},
1312
},
@@ -16,20 +15,28 @@ use crate::{
1615
PublicBuilder, PublicEccParametersBuilder, PublicKeyRsa, PublicRsaParametersBuilder,
1716
RsaExponent, RsaScheme, SymmetricDefinitionObject,
1817
},
19-
Context, Error, Result, WrapperErrorKind,
18+
Context, Result,
2019
};
21-
use std::convert::TryFrom;
20+
use std::convert::{TryFrom, TryInto};
2221
// Source: TCG EK Credential Profile for TPM Family 2.0; Level 0 Version 2.3 Revision 2
2322
// Section 2.2.1.4 (Low Range) for Windows compatibility
2423
const RSA_2048_EK_CERTIFICATE_NV_INDEX: u32 = 0x01c00002;
2524
const ECC_P256_EK_CERTIFICATE_NV_INDEX: u32 = 0x01c0000a;
2625

26+
// Source: TCG EK Credential Profile for TPM Family 2.0; Level 0 Version 2.3 Revision 2
27+
// Section 2.2.1.5 (High Range)
28+
const ECC_P384_EK_CERTIFICATE_NV_INDEX: u32 = 0x01c00016;
29+
const ECC_P521_EK_CERTIFICATE_NV_INDEX: u32 = 0x01c00018;
30+
const ECC_P256_SM2_EK_CERTIFICATE_NV_INDEX: u32 = 0x01c0001a;
31+
const RSA_3072_EK_CERTIFICATE_NV_INDEX: u32 = 0x01c0001c;
32+
const RSA_4096_EK_CERTIFICATE_NV_INDEX: u32 = 0x01c0001e;
33+
2734
/// Get the [`Public`] representing a default Endorsement Key
2835
///
2936
/// Source: TCG EK Credential Profile for TPM Family 2.0; Level 0 Version 2.3 Revision 2
3037
/// Appendix B.3.3 and B.3.4
3138
pub fn create_ek_public_from_default_template<IKC: IntoKeyCustomization>(
32-
alg: AsymmetricAlgorithm,
39+
alg: AsymmetricAlgorithmSelection,
3340
key_customization: IKC,
3441
) -> Result<Public> {
3542
let key_customization = key_customization.into_key_customization();
@@ -65,7 +72,9 @@ pub fn create_ek_public_from_default_template<IKC: IntoKeyCustomization>(
6572
];
6673

6774
let key_builder = match alg {
68-
AsymmetricAlgorithm::Rsa => PublicBuilder::new()
75+
AsymmetricAlgorithmSelection::Rsa2048
76+
| AsymmetricAlgorithmSelection::Rsa3072
77+
| AsymmetricAlgorithmSelection::Rsa4096 => PublicBuilder::new()
6978
.with_public_algorithm(PublicAlgorithm::Rsa)
7079
.with_name_hashing_algorithm(HashingAlgorithm::Sha256)
7180
.with_object_attributes(obj_attrs)
@@ -74,15 +83,18 @@ pub fn create_ek_public_from_default_template<IKC: IntoKeyCustomization>(
7483
PublicRsaParametersBuilder::new()
7584
.with_symmetric(SymmetricDefinitionObject::AES_128_CFB)
7685
.with_scheme(RsaScheme::Null)
77-
.with_key_bits(RsaKeyBits::Rsa2048)
86+
.with_key_bits(alg.try_into()?)
7887
.with_exponent(RsaExponent::default())
7988
.with_is_signing_key(obj_attrs.sign_encrypt())
8089
.with_is_decryption_key(obj_attrs.decrypt())
8190
.with_restricted(obj_attrs.decrypt())
8291
.build()?,
8392
)
8493
.with_rsa_unique_identifier(PublicKeyRsa::new_empty_with_size(RsaKeyBits::Rsa2048)),
85-
AsymmetricAlgorithm::Ecc => PublicBuilder::new()
94+
AsymmetricAlgorithmSelection::EccP256
95+
| AsymmetricAlgorithmSelection::EccP384
96+
| AsymmetricAlgorithmSelection::EccP521
97+
| AsymmetricAlgorithmSelection::EccP256Sm2 => PublicBuilder::new()
8698
.with_public_algorithm(PublicAlgorithm::Ecc)
8799
.with_name_hashing_algorithm(HashingAlgorithm::Sha256)
88100
.with_object_attributes(obj_attrs)
@@ -91,7 +103,7 @@ pub fn create_ek_public_from_default_template<IKC: IntoKeyCustomization>(
91103
PublicEccParametersBuilder::new()
92104
.with_symmetric(SymmetricDefinitionObject::AES_128_CFB)
93105
.with_ecc_scheme(EccScheme::Null)
94-
.with_curve(EccCurve::NistP256)
106+
.with_curve(alg.try_into()?)
95107
.with_key_derivation_function_scheme(KeyDerivationFunctionScheme::Null)
96108
.with_is_signing_key(obj_attrs.sign_encrypt())
97109
.with_is_decryption_key(obj_attrs.decrypt())
@@ -102,10 +114,6 @@ pub fn create_ek_public_from_default_template<IKC: IntoKeyCustomization>(
102114
EccParameter::try_from(vec![0u8; 32])?,
103115
EccParameter::try_from(vec![0u8; 32])?,
104116
)),
105-
AsymmetricAlgorithm::Null => {
106-
// TDOD: Figure out what to with Null.
107-
return Err(Error::local_error(WrapperErrorKind::UnsupportedParam));
108-
}
109117
};
110118

111119
let key_builder = if let Some(ref k) = key_customization {
@@ -119,7 +127,7 @@ pub fn create_ek_public_from_default_template<IKC: IntoKeyCustomization>(
119127
/// Create the Endorsement Key object from the specification templates
120128
pub fn create_ek_object<IKC: IntoKeyCustomization>(
121129
context: &mut Context,
122-
alg: AsymmetricAlgorithm,
130+
alg: AsymmetricAlgorithmSelection,
123131
key_customization: IKC,
124132
) -> Result<KeyHandle> {
125133
let ek_public = create_ek_public_from_default_template(alg, key_customization)?;
@@ -132,14 +140,18 @@ pub fn create_ek_object<IKC: IntoKeyCustomization>(
132140
}
133141

134142
/// Retrieve the Endorsement Key public certificate from the TPM
135-
pub fn retrieve_ek_pubcert(context: &mut Context, alg: AsymmetricAlgorithm) -> Result<Vec<u8>> {
143+
pub fn retrieve_ek_pubcert(
144+
context: &mut Context,
145+
alg: AsymmetricAlgorithmSelection,
146+
) -> Result<Vec<u8>> {
136147
let nv_idx = match alg {
137-
AsymmetricAlgorithm::Rsa => RSA_2048_EK_CERTIFICATE_NV_INDEX,
138-
AsymmetricAlgorithm::Ecc => ECC_P256_EK_CERTIFICATE_NV_INDEX,
139-
AsymmetricAlgorithm::Null => {
140-
// TDOD: Figure out what to with Null.
141-
return Err(Error::local_error(WrapperErrorKind::UnsupportedParam));
142-
}
148+
AsymmetricAlgorithmSelection::Rsa2048 => RSA_2048_EK_CERTIFICATE_NV_INDEX,
149+
AsymmetricAlgorithmSelection::Rsa3072 => RSA_3072_EK_CERTIFICATE_NV_INDEX,
150+
AsymmetricAlgorithmSelection::Rsa4096 => RSA_4096_EK_CERTIFICATE_NV_INDEX,
151+
AsymmetricAlgorithmSelection::EccP256 => ECC_P256_EK_CERTIFICATE_NV_INDEX,
152+
AsymmetricAlgorithmSelection::EccP384 => ECC_P384_EK_CERTIFICATE_NV_INDEX,
153+
AsymmetricAlgorithmSelection::EccP521 => ECC_P521_EK_CERTIFICATE_NV_INDEX,
154+
AsymmetricAlgorithmSelection::EccP256Sm2 => ECC_P256_SM2_EK_CERTIFICATE_NV_INDEX,
143155
};
144156

145157
let nv_idx = NvIndexTpmHandle::new(nv_idx).unwrap();

tss-esapi/src/abstraction/transient/key_attestation.rs

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use crate::{
66
constants::SessionType,
77
handles::{AuthHandle, KeyHandle, SessionHandle},
88
interface_types::{
9-
algorithm::{AsymmetricAlgorithm, HashingAlgorithm},
9+
algorithm::{AsymmetricAlgorithmSelection, HashingAlgorithm},
1010
session_handles::{AuthSession, PolicySession},
1111
},
1212
structures::{EncryptedSecret, IdObject, SymmetricDefinition},
@@ -154,13 +154,16 @@ impl TransientKeyContext {
154154
None,
155155
);
156156
Ok((
157-
ek::create_ek_object(&mut self.context, AsymmetricAlgorithm::Rsa, None).or_else(
158-
|e| {
159-
self.context
160-
.flush_context(SessionHandle::from(session).into())?;
161-
Err(e)
162-
},
163-
)?,
157+
ek::create_ek_object(
158+
&mut self.context,
159+
AsymmetricAlgorithmSelection::Rsa2048,
160+
None,
161+
)
162+
.or_else(|e| {
163+
self.context
164+
.flush_context(SessionHandle::from(session).into())?;
165+
Err(e)
166+
})?,
164167
session,
165168
))
166169
}
@@ -191,7 +194,7 @@ impl TransientKeyContext {
191194
}
192195

193196
fn get_ek_object_public(context: &mut crate::Context) -> Result<PublicKey> {
194-
let key_handle = ek::create_ek_object(context, AsymmetricAlgorithm::Rsa, None)?;
197+
let key_handle = ek::create_ek_object(context, AsymmetricAlgorithmSelection::Rsa2048, None)?;
195198
let (attesting_key_pub, _, _) = context.read_public(key_handle).or_else(|e| {
196199
context.flush_context(key_handle.into())?;
197200
Err(e)

tss-esapi/src/interface_types/algorithm.rs

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
// SPDX-License-Identifier: Apache-2.0
33
use crate::{
44
constants::AlgorithmIdentifier,
5+
interface_types::{ecc::EccCurve, key_bits::RsaKeyBits},
56
tss2_esys::{
67
TPMI_ALG_ASYM, TPMI_ALG_ECC_SCHEME, TPMI_ALG_HASH, TPMI_ALG_KDF, TPMI_ALG_KEYEDHASH_SCHEME,
78
TPMI_ALG_PUBLIC, TPMI_ALG_RSA_DECRYPT, TPMI_ALG_RSA_SCHEME, TPMI_ALG_SIG_SCHEME,
@@ -335,6 +336,60 @@ impl TryFrom<TPMI_ALG_ASYM> for AsymmetricAlgorithm {
335336
}
336337
}
337338

339+
/// Enum representing the asymmetric algorithm interface type with specific properties.
340+
/// Use this instead of [AsymmetricAlgorithm], which will be deprecated at some point.
341+
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
342+
pub enum AsymmetricAlgorithmSelection {
343+
Rsa2048,
344+
Rsa3072,
345+
Rsa4096,
346+
EccP256,
347+
EccP384,
348+
EccP521,
349+
EccP256Sm2,
350+
}
351+
352+
impl TryFrom<AsymmetricAlgorithm> for AsymmetricAlgorithmSelection {
353+
type Error = Error;
354+
355+
fn try_from(value: AsymmetricAlgorithm) -> std::result::Result<Self, Self::Error> {
356+
match value {
357+
AsymmetricAlgorithm::Rsa => Ok(AsymmetricAlgorithmSelection::Rsa2048),
358+
AsymmetricAlgorithm::Ecc => Ok(AsymmetricAlgorithmSelection::EccP256),
359+
AsymmetricAlgorithm::Null => {
360+
Err(Error::local_error(WrapperErrorKind::UnsupportedParam))
361+
}
362+
}
363+
}
364+
}
365+
366+
impl TryFrom<AsymmetricAlgorithmSelection> for RsaKeyBits {
367+
type Error = Error;
368+
369+
fn try_from(value: AsymmetricAlgorithmSelection) -> std::result::Result<Self, Self::Error> {
370+
match value {
371+
AsymmetricAlgorithmSelection::Rsa2048 => Ok(RsaKeyBits::Rsa2048),
372+
AsymmetricAlgorithmSelection::Rsa3072 => Ok(RsaKeyBits::Rsa3072),
373+
AsymmetricAlgorithmSelection::Rsa4096 => Ok(RsaKeyBits::Rsa4096),
374+
_ => Err(Error::local_error(WrapperErrorKind::InvalidParam)),
375+
}
376+
}
377+
}
378+
379+
impl TryFrom<AsymmetricAlgorithmSelection> for EccCurve {
380+
type Error = Error;
381+
382+
fn try_from(value: AsymmetricAlgorithmSelection) -> std::result::Result<Self, Self::Error> {
383+
match value {
384+
AsymmetricAlgorithmSelection::EccP256 => Ok(EccCurve::NistP256),
385+
AsymmetricAlgorithmSelection::EccP384 => Ok(EccCurve::NistP384),
386+
AsymmetricAlgorithmSelection::EccP521 => Ok(EccCurve::NistP521),
387+
AsymmetricAlgorithmSelection::EccP256Sm2 => Ok(EccCurve::Sm2P256),
388+
_ => Err(Error::local_error(WrapperErrorKind::InvalidParam)),
389+
}
390+
}
391+
}
392+
338393
/// Enum representing the signature scheme interface type.
339394
///
340395
/// # Details
@@ -419,6 +474,30 @@ impl TryFrom<SignatureSchemeAlgorithm> for AsymmetricAlgorithm {
419474
}
420475
}
421476

477+
// A convenience conversion into AsymmetricAlgorithmSelection
478+
// that is associated with the signature scheme.
479+
// Currently mimics the behavior of the AsymmetricAlgorithm implementation
480+
impl TryFrom<SignatureSchemeAlgorithm> for AsymmetricAlgorithmSelection {
481+
type Error = Error;
482+
fn try_from(signature_scheme: SignatureSchemeAlgorithm) -> Result<Self> {
483+
match signature_scheme {
484+
SignatureSchemeAlgorithm::RsaSsa => Ok(AsymmetricAlgorithmSelection::Rsa2048),
485+
SignatureSchemeAlgorithm::RsaPss => Ok(AsymmetricAlgorithmSelection::Rsa2048),
486+
SignatureSchemeAlgorithm::EcDsa => Ok(AsymmetricAlgorithmSelection::EccP256),
487+
SignatureSchemeAlgorithm::EcDaa => Ok(AsymmetricAlgorithmSelection::EccP256),
488+
SignatureSchemeAlgorithm::Sm2 => Ok(AsymmetricAlgorithmSelection::EccP256),
489+
SignatureSchemeAlgorithm::EcSchnorr => Ok(AsymmetricAlgorithmSelection::EccP256),
490+
_ => {
491+
// HMAC is for symmetric algorithms
492+
//
493+
// Null could be converted into AsymmetricAlgorithm::Null
494+
// but I do not know if that is useful.
495+
Err(Error::local_error(WrapperErrorKind::InvalidParam))
496+
}
497+
}
498+
}
499+
}
500+
422501
/// Enum repsenting the symmetric object inetrface type.
423502
///
424503
/// # Details

tss-esapi/tests/integration_tests/abstraction_tests/ak_tests.rs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use tss_esapi::{
99
constants::SessionType,
1010
handles::AuthHandle,
1111
interface_types::{
12-
algorithm::{AsymmetricAlgorithm, HashingAlgorithm, SignatureSchemeAlgorithm},
12+
algorithm::{AsymmetricAlgorithmSelection, HashingAlgorithm, SignatureSchemeAlgorithm},
1313
session_handles::PolicySession,
1414
},
1515
structures::{Auth, Digest, PublicBuilder, SymmetricDefinition},
@@ -21,7 +21,8 @@ use crate::common::create_ctx_without_session;
2121
fn test_create_ak_rsa_rsa() {
2222
let mut context = create_ctx_without_session();
2323

24-
let ek_rsa = ek::create_ek_object(&mut context, AsymmetricAlgorithm::Rsa, None).unwrap();
24+
let ek_rsa =
25+
ek::create_ek_object(&mut context, AsymmetricAlgorithmSelection::Rsa2048, None).unwrap();
2526
ak::create_ak(
2627
&mut context,
2728
ek_rsa,
@@ -37,7 +38,8 @@ fn test_create_ak_rsa_rsa() {
3738
fn test_create_ak_rsa_ecc() {
3839
let mut context = create_ctx_without_session();
3940

40-
let ek_rsa = ek::create_ek_object(&mut context, AsymmetricAlgorithm::Rsa, None).unwrap();
41+
let ek_rsa =
42+
ek::create_ek_object(&mut context, AsymmetricAlgorithmSelection::Rsa2048, None).unwrap();
4143
if ak::create_ak(
4244
&mut context,
4345
ek_rsa,
@@ -57,7 +59,8 @@ fn test_create_ak_rsa_ecc() {
5759
fn test_create_and_use_ak() {
5860
let mut context = create_ctx_without_session();
5961

60-
let ek_rsa = ek::create_ek_object(&mut context, AsymmetricAlgorithm::Rsa, None).unwrap();
62+
let ek_rsa =
63+
ek::create_ek_object(&mut context, AsymmetricAlgorithmSelection::Rsa2048, None).unwrap();
6164
let ak_auth = Auth::try_from(vec![0x1, 0x2, 0x42]).unwrap();
6265
let att_key = ak::create_ak(
6366
&mut context,
@@ -158,7 +161,8 @@ fn test_create_custom_ak() {
158161
}
159162
let mut context = create_ctx_without_session();
160163

161-
let ek_rsa = ek::create_ek_object(&mut context, AsymmetricAlgorithm::Rsa, None).unwrap();
164+
let ek_rsa =
165+
ek::create_ek_object(&mut context, AsymmetricAlgorithmSelection::Rsa2048, None).unwrap();
162166
let ak_auth = Auth::try_from(vec![0x1, 0x2, 0x42]).unwrap();
163167
// Without customization, no st clear
164168
let att_key_without = ak::create_ak(

0 commit comments

Comments
 (0)