From 7c4dcee6d025d534d9319ed7ad8daa7b5a950640 Mon Sep 17 00:00:00 2001 From: Thore Sommer Date: Sun, 11 Jun 2023 16:11:29 +0300 Subject: [PATCH] This adds support other keys than RSA2048 and ECC Nist P256. This takes the following PRs and from the main branch and adapts them so that they can be merged into the 7.x.y branch: \#464 (By Ionut Mihalcea ) \#414 (By Thore Sommer ) \#552 (By Thore Sommer ) Co-authored-by: Jesper Brynolf Co-authored-by: Thore Sommer Co-authored-by: Ionut Mihalcea Signed-off-by: Jesper Brynolf --- tss-esapi/src/abstraction/ak.rs | 138 +++++++++--- tss-esapi/src/abstraction/ek.rs | 203 ++++++++++++------ tss-esapi/src/abstraction/mod.rs | 37 +++- .../abstraction/transient/key_attestation.rs | 28 ++- tss-esapi/src/interface_types/algorithm.rs | 3 +- tss-esapi/src/structures/parameters.rs | 5 + tss-esapi/src/structures/tagged/public.rs | 14 +- tss-esapi/src/structures/tagged/public/ecc.rs | 30 ++- tss-esapi/src/structures/tagged/symmetric.rs | 8 + .../abstraction_tests/ak_tests.rs | 139 ++++++++++-- .../abstraction_tests/ek_tests.rs | 43 +++- .../transient_key_context_tests.rs | 25 ++- .../public_ecc_parameters_tests.rs | 69 ++++++ 13 files changed, 603 insertions(+), 139 deletions(-) diff --git a/tss-esapi/src/abstraction/ak.rs b/tss-esapi/src/abstraction/ak.rs index bf4febb13..cb0ccac34 100644 --- a/tss-esapi/src/abstraction/ak.rs +++ b/tss-esapi/src/abstraction/ak.rs @@ -2,31 +2,62 @@ // SPDX-License-Identifier: Apache-2.0 use crate::{ - abstraction::{cipher::Cipher, IntoKeyCustomization, KeyCustomization}, + abstraction::{AsymmetricAlgorithmSelection, IntoKeyCustomization, KeyCustomization}, attributes::{ObjectAttributesBuilder, SessionAttributesBuilder}, constants::{AlgorithmIdentifier, SessionType}, handles::{AuthHandle, KeyHandle, SessionHandle}, interface_types::{ algorithm::{ - AsymmetricAlgorithm, EccSchemeAlgorithm, HashingAlgorithm, PublicAlgorithm, - RsaSchemeAlgorithm, SignatureSchemeAlgorithm, + EccSchemeAlgorithm, HashingAlgorithm, PublicAlgorithm, RsaSchemeAlgorithm, + SignatureSchemeAlgorithm, }, - ecc::EccCurve, - key_bits::RsaKeyBits, session_handles::PolicySession, }, structures::{ - Auth, CreateKeyResult, EccScheme, KeyDerivationFunctionScheme, Private, Public, - PublicBuilder, PublicEccParametersBuilder, PublicKeyRsa, PublicRsaParametersBuilder, - RsaExponent, RsaScheme, SymmetricDefinitionObject, + Auth, CreateKeyResult, Digest, DigestList, EccPoint, EccScheme, + KeyDerivationFunctionScheme, Private, Public, PublicBuilder, PublicEccParametersBuilder, + PublicKeyRsa, PublicRsaParametersBuilder, RsaExponent, RsaScheme, + SymmetricDefinitionObject, }, Context, Error, Result, WrapperErrorKind, }; -use log::error; -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( - key_alg: AsymmetricAlgorithm, + key_alg: AsymmetricAlgorithmSelection, hash_alg: HashingAlgorithm, sign_alg: SignatureSchemeAlgorithm, key_customization: IKC, @@ -50,7 +81,7 @@ fn create_ak_public( .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) @@ -60,7 +91,7 @@ fn create_ak_public( 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()) @@ -68,7 +99,7 @@ fn create_ak_public( .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) @@ -78,16 +109,17 @@ fn create_ak_public( .with_ecc_scheme(EccScheme::create( EccSchemeAlgorithm::try_from(AlgorithmIdentifier::from(sign_alg))?, Some(hash_alg), - Some(0), + if sign_alg == SignatureSchemeAlgorithm::EcDaa { + Some(0) + } else { + None + }, )?) - .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)); - } + ) + .with_ecc_unique_identifier(EccPoint::default()), }; let key_builder = if let Some(ref k) = key_customization { @@ -99,6 +131,38 @@ fn create_ak_public( 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_public, _, _) = context.read_public(parent)?; + let parent_hash_alg = parent_public.name_hashing_algorithm(); + let parent_symmetric = parent_public + .symmetric_algorithm() + .ok_or_else(|| Error::local_error(WrapperErrorKind::InvalidParam))?; + + let mut policy_digests = DigestList::new(); + + match parent_hash_alg { + HashingAlgorithm::Sha384 => { + policy_digests.add(Digest::try_from(POLICY_A_SHA384.as_slice())?)?; + policy_digests.add(Digest::try_from(POLICY_C_SHA384.as_slice())?)?; + } + HashingAlgorithm::Sha512 => { + policy_digests.add(Digest::try_from(POLICY_A_SHA512.as_slice())?)?; + policy_digests.add(Digest::try_from(POLICY_C_SHA512.as_slice())?)?; + } + HashingAlgorithm::Sm3_256 => { + policy_digests.add(Digest::try_from(POLICY_A_SM3_256.as_slice())?)?; + policy_digests.add(Digest::try_from(POLICY_C_SM3_256.as_slice())?)?; + } + _ => (), + }; + + 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, @@ -107,14 +171,16 @@ pub fn load_ak( private: Private, public: Public, ) -> Result { + 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))?; @@ -142,6 +208,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) }) @@ -160,17 +233,13 @@ pub fn create_ak( context: &mut Context, parent: KeyHandle, hash_alg: HashingAlgorithm, + key_alg: AsymmetricAlgorithmSelection, sign_alg: SignatureSchemeAlgorithm, ak_auth_value: Option, key_customization: IKC, ) -> Result { - 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 (parent_hash_alg, parent_symmetric, policy_digests) = session_config(context, parent)?; let policy_auth_session = context .start_auth_session( @@ -178,8 +247,8 @@ pub fn create_ak( 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))?; @@ -207,6 +276,13 @@ pub fn create_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.create(parent, ak_pub, ak_auth_value, None, None, None) }) diff --git a/tss-esapi/src/abstraction/ek.rs b/tss-esapi/src/abstraction/ek.rs index 9d856e509..df13e76b2 100644 --- a/tss-esapi/src/abstraction/ek.rs +++ b/tss-esapi/src/abstraction/ek.rs @@ -2,11 +2,11 @@ // SPDX-License-Identifier: Apache-2.0 use crate::{ - abstraction::{nv, IntoKeyCustomization, KeyCustomization}, + abstraction::{nv, AsymmetricAlgorithmSelection, IntoKeyCustomization, KeyCustomization}, attributes::ObjectAttributesBuilder, handles::{KeyHandle, NvIndexTpmHandle, TpmHandle}, interface_types::{ - algorithm::{AsymmetricAlgorithm, HashingAlgorithm, PublicAlgorithm}, + algorithm::{HashingAlgorithm, PublicAlgorithm}, ecc::EccCurve, key_bits::RsaKeyBits, resource_handles::{Hierarchy, NvAuth}, @@ -24,22 +24,61 @@ 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; + +// Source: TCG EK Credential Profile for TPM Family 2.0; Level 0 Version 2.5 Revision 2 +// Section B.3 and B.4 +const AUTH_POLICY_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 AUTH_POLICY_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 AUTH_POLICY_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 AUTH_POLICY_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( - alg: AsymmetricAlgorithm, + alg: AsymmetricAlgorithmSelection, key_customization: IKC, ) -> Result { let key_customization = key_customization.into_key_customization(); + // 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) @@ -54,57 +93,92 @@ pub fn create_ek_public_from_default_template( } .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 { - AsymmetricAlgorithm::Rsa => 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(RsaKeyBits::Rsa2048) - .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() - .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(EccCurve::NistP256) - .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])?, - )), - AsymmetricAlgorithm::Null => { - // TDOD: Figure out what to with Null. - return Err(Error::local_error(WrapperErrorKind::UnsupportedParam)); + AsymmetricAlgorithmSelection::Rsa(key_bits) => { + let (hash_alg, auth_policy, symmetric, unique) = match key_bits { + RsaKeyBits::Rsa2048 => ( + HashingAlgorithm::Sha256, + Digest::try_from(AUTH_POLICY_A_SHA256.as_slice())?, + SymmetricDefinitionObject::AES_128_CFB, + PublicKeyRsa::new_empty_with_size(RsaKeyBits::Rsa2048), + ), + RsaKeyBits::Rsa3072 | RsaKeyBits::Rsa4096 => ( + HashingAlgorithm::Sha384, + Digest::try_from(AUTH_POLICY_B_SHA384.as_slice())?, + SymmetricDefinitionObject::AES_256_CFB, + PublicKeyRsa::default(), + ), + // 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(auth_policy) + .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, auth_policy, symmetric, xy_size) = match ecc_curve { + EccCurve::NistP256 => ( + HashingAlgorithm::Sha256, + Digest::try_from(AUTH_POLICY_A_SHA256.as_slice())?, + SymmetricDefinitionObject::AES_128_CFB, + 32, + ), + EccCurve::NistP384 => ( + HashingAlgorithm::Sha384, + Digest::try_from(AUTH_POLICY_B_SHA384.as_slice())?, + SymmetricDefinitionObject::AES_256_CFB, + 0, + ), + EccCurve::NistP521 => ( + HashingAlgorithm::Sha512, + Digest::try_from(AUTH_POLICY_B_SHA512.as_slice())?, + SymmetricDefinitionObject::AES_256_CFB, + 0, + ), + EccCurve::Sm2P256 => ( + HashingAlgorithm::Sm3_256, + Digest::try_from(AUTH_POLICY_B_SM3_256.as_slice())?, + 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(auth_policy) + .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])?, + )) } }; @@ -119,7 +193,7 @@ pub fn create_ek_public_from_default_template( /// Create the Endorsement Key object from the specification templates pub fn create_ek_object( context: &mut Context, - alg: AsymmetricAlgorithm, + alg: AsymmetricAlgorithmSelection, key_customization: IKC, ) -> Result { let ek_public = create_ek_public_from_default_template(alg, key_customization)?; @@ -132,14 +206,21 @@ pub fn create_ek_object( } /// Retrieve the Endorsement Key public certificate from the TPM -pub fn retrieve_ek_pubcert(context: &mut Context, alg: AsymmetricAlgorithm) -> Result> { +pub fn retrieve_ek_pubcert( + context: &mut Context, + alg: AsymmetricAlgorithmSelection, +) -> Result> { 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(); diff --git a/tss-esapi/src/abstraction/mod.rs b/tss-esapi/src/abstraction/mod.rs index 1c7d8d686..45aa473ec 100644 --- a/tss-esapi/src/abstraction/mod.rs +++ b/tss-esapi/src/abstraction/mod.rs @@ -9,9 +9,16 @@ pub mod pcr; pub mod public; pub mod transient; -use crate::{attributes::ObjectAttributesBuilder, structures::PublicBuilder}; +use std::convert::TryFrom; -/// KeyCustomizaion allows to adjust how a key is going to be created +use crate::{ + attributes::ObjectAttributesBuilder, + interface_types::{algorithm::AsymmetricAlgorithm, ecc::EccCurve, key_bits::RsaKeyBits}, + structures::PublicBuilder, + Error, WrapperErrorKind, +}; + +/// KeyCustomization allows to adjust how a key is going to be created pub trait KeyCustomization { /// Alter the attributes used on key creation fn attributes(&self, attributes_builder: ObjectAttributesBuilder) -> ObjectAttributesBuilder { @@ -60,3 +67,29 @@ impl IntoKeyCustomization for Option { None } } + +/// 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 for AsymmetricAlgorithmSelection { + type Error = Error; + + fn try_from(value: AsymmetricAlgorithm) -> Result { + match value { + AsymmetricAlgorithm::Rsa => Ok(AsymmetricAlgorithmSelection::Rsa(RsaKeyBits::Rsa2048)), + AsymmetricAlgorithm::Ecc => Ok(AsymmetricAlgorithmSelection::Ecc(EccCurve::NistP256)), + AsymmetricAlgorithm::Null => { + Err(Error::local_error(WrapperErrorKind::UnsupportedParam)) + } + } + } +} diff --git a/tss-esapi/src/abstraction/transient/key_attestation.rs b/tss-esapi/src/abstraction/transient/key_attestation.rs index 82a1bd48a..48a075f4e 100644 --- a/tss-esapi/src/abstraction/transient/key_attestation.rs +++ b/tss-esapi/src/abstraction/transient/key_attestation.rs @@ -2,11 +2,12 @@ // SPDX-License-Identifier: Apache-2.0 use super::{ObjectWrapper, TransientKeyContext}; use crate::{ - abstraction::ek, + abstraction::{ek, AsymmetricAlgorithmSelection}, constants::SessionType, handles::{AuthHandle, KeyHandle, SessionHandle}, interface_types::{ - algorithm::{AsymmetricAlgorithm, HashingAlgorithm}, + algorithm::HashingAlgorithm, + key_bits::RsaKeyBits, session_handles::{AuthSession, PolicySession}, }, structures::{EncryptedSecret, IdObject, SymmetricDefinition}, @@ -151,13 +152,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, )) } @@ -188,7 +192,11 @@ impl TransientKeyContext { } fn get_ek_object_public(context: &mut crate::Context) -> Result { - 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) diff --git a/tss-esapi/src/interface_types/algorithm.rs b/tss-esapi/src/interface_types/algorithm.rs index 590c66eb9..b97b308cd 100644 --- a/tss-esapi/src/interface_types/algorithm.rs +++ b/tss-esapi/src/interface_types/algorithm.rs @@ -292,7 +292,8 @@ impl TryFrom for SymmetricMode { /// Enum representing the asymmetric algorithm interface type. /// /// # Details -/// This corresponds to TPMI_ALG_ASYM +/// Use [crate::abstraction::AsymmetricAlgorithmSelection] instead where possible. +/// This corresponds to TPMI_ALG_ASYM. #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] pub enum AsymmetricAlgorithm { Rsa, diff --git a/tss-esapi/src/structures/parameters.rs b/tss-esapi/src/structures/parameters.rs index a54467186..a9e1e9801 100644 --- a/tss-esapi/src/structures/parameters.rs +++ b/tss-esapi/src/structures/parameters.rs @@ -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 for SymmetricCipherParameters { diff --git a/tss-esapi/src/structures/tagged/public.rs b/tss-esapi/src/structures/tagged/public.rs index 2768ea74d..83cfb3dab 100644 --- a/tss-esapi/src/structures/tagged/public.rs +++ b/tss-esapi/src/structures/tagged/public.rs @@ -7,7 +7,9 @@ pub mod rsa; use crate::{ attributes::ObjectAttributes, interface_types::algorithm::{HashingAlgorithm, PublicAlgorithm}, - structures::{Digest, EccPoint, PublicKeyRsa, SymmetricCipherParameters}, + structures::{ + Digest, EccPoint, PublicKeyRsa, SymmetricCipherParameters, SymmetricDefinitionObject, + }, traits::{Marshall, UnMarshall}, tss2_esys::{TPM2B_PUBLIC, TPMT_PUBLIC}, Error, Result, WrapperErrorKind, @@ -374,6 +376,16 @@ impl Public { } } + /// Returns the name symmetric definition object if available. + pub fn symmetric_algorithm(&self) -> Option { + match self { + Public::Rsa { parameters, .. } => Some(parameters.symmetric_definition_object()), + Public::KeyedHash { .. } => None, + Public::Ecc { parameters, .. } => Some(parameters.symmetric_definition_object()), + Public::SymCipher { parameters, .. } => Some(parameters.symmetric_definition_object()), + } + } + /// Returns the auth policy digest. pub fn auth_policy(&self) -> &Digest { match self { diff --git a/tss-esapi/src/structures/tagged/public/ecc.rs b/tss-esapi/src/structures/tagged/public/ecc.rs index e71cb317e..ec3ff9164 100644 --- a/tss-esapi/src/structures/tagged/public/ecc.rs +++ b/tss-esapi/src/structures/tagged/public/ecc.rs @@ -194,11 +194,31 @@ impl PublicEccParametersBuilder { return Err(Error::local_error(WrapperErrorKind::InconsistentParams)); } - if (ecc_curve == EccCurve::BnP256 || ecc_curve == EccCurve::BnP638) - && ecc_scheme.algorithm() != EccSchemeAlgorithm::EcDaa - { - error!("Bn curve should use only EcDaa scheme"); - return Err(Error::local_error(WrapperErrorKind::InconsistentParams)); + match (ecc_curve, ecc_scheme.algorithm()) { + (EccCurve::BnP256 | EccCurve::BnP638, EccSchemeAlgorithm::EcDaa) + | (EccCurve::Sm2P256, EccSchemeAlgorithm::Sm2) + | ( + EccCurve::NistP192 + | EccCurve::NistP224 + | EccCurve::NistP256 + | EccCurve::NistP384 + | EccCurve::NistP521, + EccSchemeAlgorithm::EcDh + | EccSchemeAlgorithm::EcDaa + | EccSchemeAlgorithm::EcDsa + | EccSchemeAlgorithm::EcMqv + | EccSchemeAlgorithm::EcSchnorr, + ) + | (_, EccSchemeAlgorithm::Null) => (), + + _ => { + error!( + "Mismatch between elliptic curve ({:#?}) and signing scheme ({:#?}) used", + ecc_curve, + ecc_scheme.algorithm() + ); + return Err(Error::local_error(WrapperErrorKind::InconsistentParams)); + } } Ok(PublicEccParameters { diff --git a/tss-esapi/src/structures/tagged/symmetric.rs b/tss-esapi/src/structures/tagged/symmetric.rs index 9c2f064c5..e31297281 100644 --- a/tss-esapi/src/structures/tagged/symmetric.rs +++ b/tss-esapi/src/structures/tagged/symmetric.rs @@ -160,11 +160,19 @@ impl SymmetricDefinitionObject { key_bits: AesKeyBits::Aes128, mode: SymmetricMode::Cfb, }; + /// Constant for the AES 256 bits CFB symmetric definition object pub const AES_256_CFB: SymmetricDefinitionObject = SymmetricDefinitionObject::Aes { key_bits: AesKeyBits::Aes256, mode: SymmetricMode::Cfb, }; + + // Constant for the SM4 128 bits CFB symmetric definition object + pub const SM4_128_CFB: SymmetricDefinitionObject = SymmetricDefinitionObject::Sm4 { + key_bits: Sm4KeyBits::Sm4_128, + mode: SymmetricMode::Cfb, + }; + pub(crate) fn is_null(&self) -> bool { matches!(self, Self::Null) } diff --git a/tss-esapi/tests/integration_tests/abstraction_tests/ak_tests.rs b/tss-esapi/tests/integration_tests/abstraction_tests/ak_tests.rs index ad2a1691b..3db953da4 100644 --- a/tss-esapi/tests/integration_tests/abstraction_tests/ak_tests.rs +++ b/tss-esapi/tests/integration_tests/abstraction_tests/ak_tests.rs @@ -4,15 +4,18 @@ use std::convert::{TryFrom, TryInto}; use tss_esapi::{ - abstraction::{ak, ek, KeyCustomization}, + abstraction::{ak, ek, AsymmetricAlgorithmSelection, KeyCustomization}, attributes::{ObjectAttributesBuilder, SessionAttributesBuilder}, constants::SessionType, handles::AuthHandle, interface_types::{ - algorithm::{AsymmetricAlgorithm, HashingAlgorithm, SignatureSchemeAlgorithm}, + algorithm::{HashingAlgorithm, SignatureSchemeAlgorithm}, + ecc::EccCurve, + key_bits::RsaKeyBits, session_handles::PolicySession, }, structures::{Auth, Digest, PublicBuilder, SymmetricDefinition}, + Error, WrapperErrorKind, }; use crate::common::create_ctx_without_session; @@ -21,48 +24,150 @@ 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, ) .unwrap(); + context.flush_context(ek_rsa.into()).unwrap(); +} + +#[test] +fn test_create_ak_rsa_rsa_3072() { + let mut context = create_ctx_without_session(); + + let ek_rsa = ek::create_ek_object( + &mut context, + AsymmetricAlgorithmSelection::Rsa(RsaKeyBits::Rsa3072), + None, + ) + .unwrap(); + ak::create_ak( + &mut context, + ek_rsa, + HashingAlgorithm::Sha384, + AsymmetricAlgorithmSelection::Rsa(RsaKeyBits::Rsa3072), + SignatureSchemeAlgorithm::RsaPss, + None, + None, + ) + .unwrap(); + context.flush_context(ek_rsa.into()).unwrap(); } #[test] 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(); - if ak::create_ak( + let ek_rsa = ek::create_ek_object( + &mut context, + AsymmetricAlgorithmSelection::Rsa(RsaKeyBits::Rsa2048), + None, + ) + .unwrap(); + + if let Err(actual_error) = ak::create_ak( &mut context, ek_rsa, HashingAlgorithm::Sha256, + AsymmetricAlgorithmSelection::Ecc(EccCurve::NistP256), SignatureSchemeAlgorithm::Sm2, None, None, - ) - .is_ok() - { - // We can't use unwrap_err because that requires Debug on the T - panic!("Should have errored"); + ) { + let expected_error = Error::WrapperError(WrapperErrorKind::InconsistentParams); + assert_eq!(expected_error, actual_error); + } else { + // We can't use unwrap_err because that requires Debug on the T(=CreateKeyResult). + panic!("Should not be possible to create an AK with a parent that have an unsupported or incompatible scheme."); } } +#[test] +fn test_create_ak_ecc_ecc() { + let mut context = create_ctx_without_session(); + + let ek_ecc = ek::create_ek_object( + &mut context, + AsymmetricAlgorithmSelection::Ecc(EccCurve::NistP384), + None, + ) + .unwrap(); + + let ak_res = ak::create_ak( + &mut context, + ek_ecc, + HashingAlgorithm::Sha384, + AsymmetricAlgorithmSelection::Ecc(EccCurve::NistP384), + SignatureSchemeAlgorithm::EcDsa, + None, + None, + ) + .unwrap(); + + let ak_ecc = ak::load_ak( + &mut context, + ek_ecc, + None, + ak_res.out_private, + ak_res.out_public, + ) + .unwrap(); + + context.flush_context(ek_ecc.into()).unwrap(); + context.flush_context(ak_ecc.into()).unwrap(); +} + +#[test] +fn test_create_ak_ecdaa() { + let mut context = create_ctx_without_session(); + + let ek_ecc = ek::create_ek_object( + &mut context, + AsymmetricAlgorithmSelection::Ecc(EccCurve::NistP384), + None, + ) + .unwrap(); + ak::create_ak( + &mut context, + ek_ecc, + HashingAlgorithm::Sha256, + AsymmetricAlgorithmSelection::Ecc(EccCurve::BnP256), + SignatureSchemeAlgorithm::EcDaa, + None, + None, + ) + .unwrap(); + context.flush_context(ek_ecc.into()).unwrap(); +} + #[test] 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, @@ -139,6 +244,9 @@ fn test_create_and_use_ak() { .unwrap(); assert_eq!(expected, decrypted); + + context.flush_context(ek_rsa.into()).unwrap(); + context.flush_context(loaded_ak.into()).unwrap(); } #[test] @@ -158,13 +266,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, @@ -181,6 +295,7 @@ fn test_create_custom_ak() { &mut context, ek_rsa, HashingAlgorithm::Sha256, + AsymmetricAlgorithmSelection::Rsa(RsaKeyBits::Rsa2048), SignatureSchemeAlgorithm::RsaPss, Some(ak_auth), &CustomizeKey, diff --git a/tss-esapi/tests/integration_tests/abstraction_tests/ek_tests.rs b/tss-esapi/tests/integration_tests/abstraction_tests/ek_tests.rs index fd9de7531..684ab91bf 100644 --- a/tss-esapi/tests/integration_tests/abstraction_tests/ek_tests.rs +++ b/tss-esapi/tests/integration_tests/abstraction_tests/ek_tests.rs @@ -2,9 +2,9 @@ // SPDX-License-Identifier: Apache-2.0 use tss_esapi::{ - abstraction::ek, + abstraction::{ek, AsymmetricAlgorithmSelection}, constants::response_code::{FormatOneResponseCode, Tss2ResponseCode}, - interface_types::algorithm::AsymmetricAlgorithm, + interface_types::{ecc::EccCurve, key_bits::RsaKeyBits}, Error, }; @@ -16,12 +16,18 @@ fn test_retrieve_ek_pubcert() { // The error 395 is for "handle could not be found" - this makes it that if the NV Index // did not exist (the test is run on a TPM without an endorsement cert), it still passes. - match ek::retrieve_ek_pubcert(&mut context, AsymmetricAlgorithm::Rsa) { + match ek::retrieve_ek_pubcert( + &mut context, + AsymmetricAlgorithmSelection::Rsa(RsaKeyBits::Rsa2048), + ) { Ok(_) => (), Err(Error::Tss2Error(Tss2ResponseCode::FormatOne(FormatOneResponseCode(395)))) => (), Err(e) => panic!("Error was unexpected: {:?}", e), }; - match ek::retrieve_ek_pubcert(&mut context, AsymmetricAlgorithm::Ecc) { + match ek::retrieve_ek_pubcert( + &mut context, + AsymmetricAlgorithmSelection::Ecc(EccCurve::NistP256), + ) { Ok(_) => (), Err(Error::Tss2Error(Tss2ResponseCode::FormatOne(FormatOneResponseCode(395)))) => (), Err(e) => panic!("Error was unexpected: {:?}", e), @@ -29,9 +35,32 @@ fn test_retrieve_ek_pubcert() { } #[test] -fn test_create_ek() { +fn test_create_ek_rsa() { + // RSA key sizes currently supported by swtpm + let supported_ek_sizes = vec![RsaKeyBits::Rsa2048, RsaKeyBits::Rsa3072]; let mut context = create_ctx_without_session(); - let _ = ek::create_ek_object(&mut context, AsymmetricAlgorithm::Rsa, None).unwrap(); - let _ = ek::create_ek_object(&mut context, AsymmetricAlgorithm::Ecc, None).unwrap(); + for key_bits in supported_ek_sizes { + let handle = ek::create_ek_object( + &mut context, + AsymmetricAlgorithmSelection::Rsa(key_bits), + None, + ) + .unwrap_or_else(|_| panic!("failed to create EK {:?}", key_bits)); + context.flush_context(handle.into()).unwrap(); + } +} + +#[test] +fn test_create_ek_ecc() { + // ECC curves currently supported by swtpm + let supported_ek_curves = vec![EccCurve::NistP256, EccCurve::NistP384]; + let mut context = create_ctx_without_session(); + + for curve in supported_ek_curves { + let handle = + ek::create_ek_object(&mut context, AsymmetricAlgorithmSelection::Ecc(curve), None) + .unwrap_or_else(|_| panic!("failed to create EK {:?}", curve)); + context.flush_context(handle.into()).unwrap(); + } } diff --git a/tss-esapi/tests/integration_tests/abstraction_tests/transient_key_context_tests.rs b/tss-esapi/tests/integration_tests/abstraction_tests/transient_key_context_tests.rs index f07310f81..b512e1edb 100644 --- a/tss-esapi/tests/integration_tests/abstraction_tests/transient_key_context_tests.rs +++ b/tss-esapi/tests/integration_tests/abstraction_tests/transient_key_context_tests.rs @@ -2,13 +2,14 @@ // SPDX-License-Identifier: Apache-2.0 use std::convert::{TryFrom, TryInto}; use tss_esapi::{ - abstraction::ek, - abstraction::transient::{KeyParams, ObjectWrapper, TransientKeyContextBuilder}, + abstraction::{ + ek, + transient::{KeyParams, ObjectWrapper, TransientKeyContextBuilder}, + AsymmetricAlgorithmSelection, + }, constants::response_code::Tss2ResponseCodeKind, interface_types::{ - algorithm::{ - AsymmetricAlgorithm, EccSchemeAlgorithm, HashingAlgorithm, RsaSchemeAlgorithm, - }, + algorithm::{EccSchemeAlgorithm, HashingAlgorithm, RsaSchemeAlgorithm}, ecc::EccCurve, key_bits::RsaKeyBits, resource_handles::Hierarchy, @@ -630,8 +631,11 @@ fn activate_credential() { let mut basic_ctx = crate::common::create_ctx_with_session(); // the public part of the EK is used, so we retrieve the parameters - let key_pub = - ek::create_ek_public_from_default_template(AsymmetricAlgorithm::Rsa, None).unwrap(); + let key_pub = ek::create_ek_public_from_default_template( + AsymmetricAlgorithmSelection::Rsa(RsaKeyBits::Rsa2048), + None, + ) + .unwrap(); let key_pub = if let Public::Rsa { object_attributes, name_hashing_algorithm, @@ -749,8 +753,11 @@ fn activate_credential_wrong_key() { let mut basic_ctx = crate::common::create_ctx_with_session(); // the public part of the EK is used, so we retrieve the parameters - let key_pub = - ek::create_ek_public_from_default_template(AsymmetricAlgorithm::Rsa, None).unwrap(); + let key_pub = ek::create_ek_public_from_default_template( + AsymmetricAlgorithmSelection::Rsa(RsaKeyBits::Rsa2048), + None, + ) + .unwrap(); let key_pub = if let Public::Rsa { object_attributes, name_hashing_algorithm, diff --git a/tss-esapi/tests/integration_tests/structures_tests/tagged_tests/public_ecc_parameters_tests.rs b/tss-esapi/tests/integration_tests/structures_tests/tagged_tests/public_ecc_parameters_tests.rs index eb23c331f..d9420e330 100644 --- a/tss-esapi/tests/integration_tests/structures_tests/tagged_tests/public_ecc_parameters_tests.rs +++ b/tss-esapi/tests/integration_tests/structures_tests/tagged_tests/public_ecc_parameters_tests.rs @@ -92,3 +92,72 @@ fn test_signing_with_wrong_symmetric() { Err(Error::WrapperError(WrapperErrorKind::InconsistentParams)) )); } + +#[test] +fn test_signing_with_mismatched_scheme_nist() { + assert_eq!( + PublicEccParametersBuilder::new() + .with_restricted(false) + .with_is_decryption_key(false) + .with_is_signing_key(true) + .with_curve(EccCurve::NistP256) + .with_ecc_scheme( + EccScheme::create( + EccSchemeAlgorithm::Sm2, + Some(HashingAlgorithm::Sha256), + None + ) + .unwrap() + ) + .with_key_derivation_function_scheme(KeyDerivationFunctionScheme::Null) + .with_symmetric(SymmetricDefinitionObject::Null) + .build(), + Err(Error::WrapperError(WrapperErrorKind::InconsistentParams)) + ); +} + +#[test] +fn test_signing_with_mismatched_scheme_sm2() { + assert_eq!( + PublicEccParametersBuilder::new() + .with_restricted(false) + .with_is_decryption_key(false) + .with_is_signing_key(true) + .with_curve(EccCurve::Sm2P256) + .with_ecc_scheme( + EccScheme::create( + EccSchemeAlgorithm::EcDsa, + Some(HashingAlgorithm::Sha256), + None + ) + .unwrap() + ) + .with_key_derivation_function_scheme(KeyDerivationFunctionScheme::Null) + .with_symmetric(SymmetricDefinitionObject::Null) + .build(), + Err(Error::WrapperError(WrapperErrorKind::InconsistentParams)) + ); +} + +#[test] +fn test_signing_with_mismatched_scheme_bn() { + assert_eq!( + PublicEccParametersBuilder::new() + .with_restricted(false) + .with_is_decryption_key(false) + .with_is_signing_key(true) + .with_curve(EccCurve::BnP256) + .with_ecc_scheme( + EccScheme::create( + EccSchemeAlgorithm::EcDsa, + Some(HashingAlgorithm::Sha256), + None + ) + .unwrap() + ) + .with_key_derivation_function_scheme(KeyDerivationFunctionScheme::Null) + .with_symmetric(SymmetricDefinitionObject::Null) + .build(), + Err(Error::WrapperError(WrapperErrorKind::InconsistentParams)) + ); +}