From 5590896971850e0676602b4be0fd5ef0778a2f15 Mon Sep 17 00:00:00 2001 From: Jesper Brynolf Date: Sat, 30 Nov 2024 12:23:35 +0100 Subject: [PATCH] Fixes API breaking changes. Signed-off-by: Jesper Brynolf --- tss-esapi/src/abstraction/ak.rs | 48 +++- tss-esapi/src/abstraction/ek.rs | 59 +++- .../abstraction/transient/key_attestation.rs | 4 +- .../abstraction_tests/ak_tests.rs | 269 ++++++++++++++++-- .../abstraction_tests/ek_tests.rs | 28 +- .../transient_key_context_tests.rs | 183 +++++++++++- 6 files changed, 558 insertions(+), 33 deletions(-) diff --git a/tss-esapi/src/abstraction/ak.rs b/tss-esapi/src/abstraction/ak.rs index cb0ccac3..51743184 100644 --- a/tss-esapi/src/abstraction/ak.rs +++ b/tss-esapi/src/abstraction/ak.rs @@ -8,8 +8,8 @@ use crate::{ handles::{AuthHandle, KeyHandle, SessionHandle}, interface_types::{ algorithm::{ - EccSchemeAlgorithm, HashingAlgorithm, PublicAlgorithm, RsaSchemeAlgorithm, - SignatureSchemeAlgorithm, + AsymmetricAlgorithm, EccSchemeAlgorithm, HashingAlgorithm, PublicAlgorithm, + RsaSchemeAlgorithm, SignatureSchemeAlgorithm, }, session_handles::PolicySession, }, @@ -21,6 +21,7 @@ use crate::{ }, Context, Error, Result, WrapperErrorKind, }; +use log::error; use std::convert::TryFrom; // Source: TCG EK Credential Profile for TPM Family 2.0; Level 0 Version 2.5 Revision 2 @@ -56,6 +57,7 @@ const POLICY_C_SM3_256: [u8; 32] = [ 0x56, 0x99, 0xa3, 0xe3, 0x9f, 0xc3, 0x55, 0x1b, 0xfe, 0xff, 0xcf, 0x13, 0x2b, 0x49, 0xe1, 0x1d, ]; +/// Creates a Public object for an AK key. fn create_ak_public( key_alg: AsymmetricAlgorithmSelection, hash_alg: HashingAlgorithm, @@ -131,7 +133,7 @@ fn create_ak_public( key_builder.build() } -// extracts the hashing and sysmmetric algorithm from parent and constructs the correct DigestList for OR policy +/// Extracts the hashing and symmetric algorithm from parent and constructs the correct DigestList for OR policy fn session_config( context: &mut Context, parent: KeyHandle, @@ -228,8 +230,46 @@ pub fn load_ak( Ok(key_handle) } -/// This creates an Attestation Key in the Endorsement hierarchy +/// This creates an Attestation Key in the Endorsement hierarchy. +/// +///
+/// +/// The API of this function will be changed to that of [`create_ak_2`] +/// in the next major version. +/// +///
pub fn create_ak( + context: &mut Context, + parent: KeyHandle, + hash_alg: HashingAlgorithm, + 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 + })?; + create_ak_2( + context, + parent, + hash_alg, + AsymmetricAlgorithmSelection::try_from(key_alg)?, + sign_alg, + ak_auth_value, + key_customization, + ) +} + +/// This creates an Attestation Key in the Endorsement hierarchy. +/// +///
+/// +/// This function will be removed in the next major version. +/// +///
+pub fn create_ak_2( context: &mut Context, parent: KeyHandle, hash_alg: HashingAlgorithm, diff --git a/tss-esapi/src/abstraction/ek.rs b/tss-esapi/src/abstraction/ek.rs index df13e76b..1637aaed 100644 --- a/tss-esapi/src/abstraction/ek.rs +++ b/tss-esapi/src/abstraction/ek.rs @@ -6,7 +6,7 @@ use crate::{ attributes::ObjectAttributesBuilder, handles::{KeyHandle, NvIndexTpmHandle, TpmHandle}, interface_types::{ - algorithm::{HashingAlgorithm, PublicAlgorithm}, + algorithm::{AsymmetricAlgorithm, HashingAlgorithm, PublicAlgorithm}, ecc::EccCurve, key_bits::RsaKeyBits, resource_handles::{Hierarchy, NvAuth}, @@ -60,7 +60,36 @@ const AUTH_POLICY_B_SM3_256: [u8; 32] = [ /// /// 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 +/// +///
+/// +/// The API of this function will be changed to that of [`create_ek_public_from_default_template_2`] +/// in the next major version. +/// +///
pub fn create_ek_public_from_default_template( + alg: AsymmetricAlgorithm, + key_customization: IKC, +) -> Result { + create_ek_public_from_default_template_2( + AsymmetricAlgorithmSelection::try_from(alg)?, + key_customization, + ) +} + +/// 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 +/// +///
+/// +/// This function will be removed in the next major version. +/// +///
+pub fn create_ek_public_from_default_template_2( alg: AsymmetricAlgorithmSelection, key_customization: IKC, ) -> Result { @@ -191,12 +220,38 @@ pub fn create_ek_public_from_default_template( } /// Create the Endorsement Key object from the specification templates +/// +///
+/// +/// The API of this function will be changed to that of [`create_ek_object_2`] +/// in the next major version. +/// +///
pub fn create_ek_object( + context: &mut Context, + alg: AsymmetricAlgorithm, + key_customization: IKC, +) -> Result { + create_ek_object_2( + context, + AsymmetricAlgorithmSelection::try_from(alg)?, + key_customization, + ) +} + +/// Create the Endorsement Key object from the specification templates +/// +///
+/// +/// This function will be removed in the next major version. +/// +///
+pub fn create_ek_object_2( context: &mut Context, alg: AsymmetricAlgorithmSelection, key_customization: IKC, ) -> Result { - let ek_public = create_ek_public_from_default_template(alg, key_customization)?; + let ek_public = create_ek_public_from_default_template_2(alg, key_customization)?; Ok(context .execute_with_nullauth_session(|ctx| { diff --git a/tss-esapi/src/abstraction/transient/key_attestation.rs b/tss-esapi/src/abstraction/transient/key_attestation.rs index 48a075f4..5d39bbbe 100644 --- a/tss-esapi/src/abstraction/transient/key_attestation.rs +++ b/tss-esapi/src/abstraction/transient/key_attestation.rs @@ -152,7 +152,7 @@ impl TransientKeyContext { None, ); Ok(( - ek::create_ek_object( + ek::create_ek_object_2( &mut self.context, AsymmetricAlgorithmSelection::Rsa(RsaKeyBits::Rsa2048), None, @@ -192,7 +192,7 @@ impl TransientKeyContext { } fn get_ek_object_public(context: &mut crate::Context) -> Result { - let key_handle = ek::create_ek_object( + let key_handle = ek::create_ek_object_2( context, AsymmetricAlgorithmSelection::Rsa(RsaKeyBits::Rsa2048), None, 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 3db953da..7c9748d3 100644 --- a/tss-esapi/tests/integration_tests/abstraction_tests/ak_tests.rs +++ b/tss-esapi/tests/integration_tests/abstraction_tests/ak_tests.rs @@ -9,7 +9,7 @@ use tss_esapi::{ constants::SessionType, handles::AuthHandle, interface_types::{ - algorithm::{HashingAlgorithm, SignatureSchemeAlgorithm}, + algorithm::{AsymmetricAlgorithm, HashingAlgorithm, SignatureSchemeAlgorithm}, ecc::EccCurve, key_bits::RsaKeyBits, session_handles::PolicySession, @@ -24,13 +24,30 @@ 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( + let ek_rsa = ek::create_ek_object(&mut context, AsymmetricAlgorithm::Rsa, None).unwrap(); + ak::create_ak( + &mut context, + ek_rsa, + HashingAlgorithm::Sha256, + SignatureSchemeAlgorithm::RsaPss, + None, + None, + ) + .unwrap(); + context.flush_context(ek_rsa.into()).unwrap(); +} + +#[test] +fn test_create_ak_2_rsa_rsa() { + let mut context = create_ctx_without_session(); + + let ek_rsa = ek::create_ek_object_2( &mut context, AsymmetricAlgorithmSelection::Rsa(RsaKeyBits::Rsa2048), None, ) .unwrap(); - ak::create_ak( + ak::create_ak_2( &mut context, ek_rsa, HashingAlgorithm::Sha256, @@ -44,16 +61,16 @@ fn test_create_ak_rsa_rsa() { } #[test] -fn test_create_ak_rsa_rsa_3072() { +fn test_create_ak_2_rsa_rsa_3072() { let mut context = create_ctx_without_session(); - let ek_rsa = ek::create_ek_object( + let ek_rsa = ek::create_ek_object_2( &mut context, AsymmetricAlgorithmSelection::Rsa(RsaKeyBits::Rsa3072), None, ) .unwrap(); - ak::create_ak( + ak::create_ak_2( &mut context, ek_rsa, HashingAlgorithm::Sha384, @@ -70,14 +87,36 @@ fn test_create_ak_rsa_rsa_3072() { fn test_create_ak_rsa_ecc() { let mut context = create_ctx_without_session(); - let ek_rsa = ek::create_ek_object( + let ek_rsa = ek::create_ek_object(&mut context, AsymmetricAlgorithm::Rsa, None).unwrap(); + + if let Err(actual_error) = ak::create_ak( + &mut context, + ek_rsa, + HashingAlgorithm::Sha256, + SignatureSchemeAlgorithm::Sm2, + None, + None, + ) { + 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_2_rsa_ecc() { + let mut context = create_ctx_without_session(); + + let ek_rsa = ek::create_ek_object_2( &mut context, AsymmetricAlgorithmSelection::Rsa(RsaKeyBits::Rsa2048), None, ) .unwrap(); - if let Err(actual_error) = ak::create_ak( + if let Err(actual_error) = ak::create_ak_2( &mut context, ek_rsa, HashingAlgorithm::Sha256, @@ -98,14 +137,43 @@ fn test_create_ak_rsa_ecc() { fn test_create_ak_ecc_ecc() { let mut context = create_ctx_without_session(); - let ek_ecc = ek::create_ek_object( + let ek_ecc = ek::create_ek_object(&mut context, AsymmetricAlgorithm::Ecc, None).unwrap(); + + let ak_res = ak::create_ak( + &mut context, + ek_ecc, + HashingAlgorithm::Sha384, + 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_2_ecc_ecc() { + let mut context = create_ctx_without_session(); + + let ek_ecc = ek::create_ek_object_2( &mut context, AsymmetricAlgorithmSelection::Ecc(EccCurve::NistP384), None, ) .unwrap(); - let ak_res = ak::create_ak( + let ak_res = ak::create_ak_2( &mut context, ek_ecc, HashingAlgorithm::Sha384, @@ -133,13 +201,30 @@ fn test_create_ak_ecc_ecc() { fn test_create_ak_ecdaa() { let mut context = create_ctx_without_session(); - let ek_ecc = ek::create_ek_object( + let ek_ecc = ek::create_ek_object(&mut context, AsymmetricAlgorithm::Ecc, None).unwrap(); + ak::create_ak( + &mut context, + ek_ecc, + HashingAlgorithm::Sha256, + SignatureSchemeAlgorithm::EcDaa, + None, + None, + ) + .unwrap(); + context.flush_context(ek_ecc.into()).unwrap(); +} + +#[test] +fn test_create_ak_2_ecdaa() { + let mut context = create_ctx_without_session(); + + let ek_ecc = ek::create_ek_object_2( &mut context, AsymmetricAlgorithmSelection::Ecc(EccCurve::NistP384), None, ) .unwrap(); - ak::create_ak( + ak::create_ak_2( &mut context, ek_ecc, HashingAlgorithm::Sha256, @@ -156,14 +241,102 @@ fn test_create_ak_ecdaa() { fn test_create_and_use_ak() { let mut context = create_ctx_without_session(); - let ek_rsa = ek::create_ek_object( + let ek_rsa = ek::create_ek_object(&mut context, AsymmetricAlgorithm::Rsa, 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, + SignatureSchemeAlgorithm::RsaPss, + Some(ak_auth.clone()), + None, + ) + .unwrap(); + + let loaded_ak = ak::load_ak( + &mut context, + ek_rsa, + Some(ak_auth), + att_key.out_private, + att_key.out_public, + ) + .unwrap(); + + let (_, key_name, _) = context.read_public(loaded_ak).unwrap(); + let cred = vec![1, 2, 3, 4, 5]; + let expected = Digest::try_from(vec![1, 2, 3, 4, 5]).unwrap(); + + let (session_aastributes, session_attributes_mask) = SessionAttributesBuilder::new().build(); + let session_1 = context + .start_auth_session( + None, + None, + None, + SessionType::Hmac, + SymmetricDefinition::AES_256_CFB, + HashingAlgorithm::Sha256, + ) + .expect("Failed to call start_auth_session") + .expect("Failed invalid session value"); + context + .tr_sess_set_attributes(session_1, session_aastributes, session_attributes_mask) + .unwrap(); + let session_2 = context + .start_auth_session( + None, + None, + None, + SessionType::Policy, + SymmetricDefinition::AES_256_CFB, + HashingAlgorithm::Sha256, + ) + .expect("Failed to call start_auth_session") + .expect("Failed invalid session value"); + context + .tr_sess_set_attributes(session_2, session_aastributes, session_attributes_mask) + .expect("Failed to call tr_sess_set_attributes"); + + let (credential_blob, secret) = context + .execute_without_session(|ctx| { + ctx.make_credential(ek_rsa, cred.try_into().unwrap(), key_name) + }) + .unwrap(); + + let _ = context + .execute_with_session(Some(session_1), |ctx| { + ctx.policy_secret( + PolicySession::try_from(session_2) + .expect("Failed to convert auth session to policy session"), + AuthHandle::Endorsement, + Default::default(), + Default::default(), + Default::default(), + None, + ) + }) + .unwrap(); + + context.set_sessions((Some(session_1), Some(session_2), None)); + + let decrypted = context + .activate_credential(loaded_ak, ek_rsa, credential_blob, secret) + .unwrap(); + + assert_eq!(expected, decrypted); +} + +#[test] +fn test_create_and_use_ak_2() { + let mut context = create_ctx_without_session(); + + let ek_rsa = ek::create_ek_object_2( &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( + let att_key = ak::create_ak_2( &mut context, ek_rsa, HashingAlgorithm::Sha256, @@ -266,7 +439,69 @@ fn test_create_custom_ak() { } let mut context = create_ctx_without_session(); - let ek_rsa = ek::create_ek_object( + let ek_rsa = ek::create_ek_object(&mut context, AsymmetricAlgorithm::Rsa, 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, + SignatureSchemeAlgorithm::RsaPss, + Some(ak_auth.clone()), + None, + ) + .unwrap(); + + assert!( + !att_key_without.out_public.object_attributes().st_clear(), + "ST Clear was set" + ); + + // With a customization, we get a new attribute + let att_key = ak::create_ak( + &mut context, + ek_rsa, + HashingAlgorithm::Sha256, + SignatureSchemeAlgorithm::RsaPss, + Some(ak_auth), + &CustomizeKey, + ) + .unwrap(); + + assert_eq!( + att_key.out_public.object_attributes().0 & tss_esapi::constants::tss::TPMA_OBJECT_STCLEAR, + tss_esapi::constants::tss::TPMA_OBJECT_STCLEAR + ); + assert_eq!( + att_key.out_public.object_attributes().0, + att_key_without.out_public.object_attributes().0 + | tss_esapi::constants::tss::TPMA_OBJECT_STCLEAR + ); + + assert_eq!( + att_key.out_public.name_hashing_algorithm(), + HashingAlgorithm::Sha1, + ); +} + +#[test] +fn test_create_custom_ak_2() { + struct CustomizeKey; + impl KeyCustomization for &CustomizeKey { + fn attributes( + &self, + attributes_builder: ObjectAttributesBuilder, + ) -> ObjectAttributesBuilder { + attributes_builder.with_st_clear(true) + } + + fn template(&self, template_builder: PublicBuilder) -> PublicBuilder { + template_builder.with_name_hashing_algorithm(HashingAlgorithm::Sha1) + } + } + let mut context = create_ctx_without_session(); + + let ek_rsa = ek::create_ek_object_2( &mut context, AsymmetricAlgorithmSelection::Rsa(RsaKeyBits::Rsa2048), None, @@ -274,7 +509,7 @@ fn test_create_custom_ak() { .unwrap(); let ak_auth = Auth::try_from(vec![0x1, 0x2, 0x42]).unwrap(); // Without customization, no st clear - let att_key_without = ak::create_ak( + let att_key_without = ak::create_ak_2( &mut context, ek_rsa, HashingAlgorithm::Sha256, @@ -291,7 +526,7 @@ fn test_create_custom_ak() { ); // With a customization, we get a new attribute - let att_key = ak::create_ak( + let att_key = ak::create_ak_2( &mut context, ek_rsa, HashingAlgorithm::Sha256, 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 684ab91b..b32b08f2 100644 --- a/tss-esapi/tests/integration_tests/abstraction_tests/ek_tests.rs +++ b/tss-esapi/tests/integration_tests/abstraction_tests/ek_tests.rs @@ -4,7 +4,7 @@ use tss_esapi::{ abstraction::{ek, AsymmetricAlgorithmSelection}, constants::response_code::{FormatOneResponseCode, Tss2ResponseCode}, - interface_types::{ecc::EccCurve, key_bits::RsaKeyBits}, + interface_types::{algorithm::AsymmetricAlgorithm, ecc::EccCurve, key_bits::RsaKeyBits}, Error, }; @@ -36,31 +36,49 @@ fn test_retrieve_ek_pubcert() { #[test] fn test_create_ek_rsa() { + let mut context = create_ctx_without_session(); + + let handle = ek::create_ek_object(&mut context, AsymmetricAlgorithm::Rsa, None) + .unwrap_or_else(|_| panic!("failed to create EK (create_ek)")); + context.flush_context(handle.into()).unwrap(); +} + +#[test] +fn test_create_ek_rsa_2() { // RSA key sizes currently supported by swtpm let supported_ek_sizes = vec![RsaKeyBits::Rsa2048, RsaKeyBits::Rsa3072]; let mut context = create_ctx_without_session(); for key_bits in supported_ek_sizes { - let handle = ek::create_ek_object( + let handle = ek::create_ek_object_2( &mut context, AsymmetricAlgorithmSelection::Rsa(key_bits), None, ) - .unwrap_or_else(|_| panic!("failed to create EK {:?}", key_bits)); + .unwrap_or_else(|_| panic!("failed to create EK (create_ek_2) {:?}", key_bits)); context.flush_context(handle.into()).unwrap(); } } #[test] fn test_create_ek_ecc() { + let mut context = create_ctx_without_session(); + + let handle = ek::create_ek_object(&mut context, AsymmetricAlgorithm::Ecc, None) + .unwrap_or_else(|_| panic!("failed to create EK (create_ek)")); + context.flush_context(handle.into()).unwrap(); +} + +#[test] +fn test_create_ek_ecc_2() { // 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)); + ek::create_ek_object_2(&mut context, AsymmetricAlgorithmSelection::Ecc(curve), None) + .unwrap_or_else(|_| panic!("failed to create EK (create_ek_2) {:?}", 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 b512e1ed..a223455f 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 @@ -9,7 +9,9 @@ use tss_esapi::{ }, constants::response_code::Tss2ResponseCodeKind, interface_types::{ - algorithm::{EccSchemeAlgorithm, HashingAlgorithm, RsaSchemeAlgorithm}, + algorithm::{ + AsymmetricAlgorithm, EccSchemeAlgorithm, HashingAlgorithm, RsaSchemeAlgorithm, + }, ecc::EccCurve, key_bits::RsaKeyBits, resource_handles::Hierarchy, @@ -631,7 +633,85 @@ 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( + let key_pub = + ek::create_ek_public_from_default_template(AsymmetricAlgorithm::Rsa, None).unwrap(); + let key_pub = if let Public::Rsa { + object_attributes, + name_hashing_algorithm, + auth_policy, + parameters, + .. + } = key_pub + { + Public::Rsa { + object_attributes, + name_hashing_algorithm, + auth_policy, + parameters, + unique: if let PublicKey::Rsa(val) = make_cred_params.attesting_key_pub { + PublicKeyRsa::try_from(val).unwrap() + } else { + panic!("Wrong public key type"); + }, + } + } else { + panic!("Wrong Public type"); + }; + let pub_handle = basic_ctx + .load_external_public(key_pub, Hierarchy::Owner) + .unwrap(); + + // Credential to expect back as proof for attestation + let credential = vec![0x53; 16]; + + let (cred, secret) = basic_ctx + .make_credential( + pub_handle, + credential.clone().try_into().unwrap(), + make_cred_params.name.try_into().unwrap(), + ) + .unwrap(); + + drop(basic_ctx); + + // Create a new Transient key context and activate the credential + let mut ctx = create_ctx(); + let cred_back = ctx + .activate_credential(obj, None, cred.value().to_vec(), secret.value().to_vec()) + .unwrap(); + + assert_eq!(cred_back, credential); +} + +#[test] +fn activate_credential_2() { + // create a Transient key context, generate a key and + // obtain the Make Credential parameters + let mut ctx = create_ctx(); + let params = KeyParams::Ecc { + curve: EccCurve::NistP256, + scheme: EccScheme::create( + EccSchemeAlgorithm::EcDsa, + Some(HashingAlgorithm::Sha256), + None, + ) + .expect("Failed to create ecc scheme"), + }; + let (material, auth) = ctx.create_key(params, 16).unwrap(); + let obj = ObjectWrapper { + material, + params, + auth, + }; + let make_cred_params = ctx.get_make_cred_params(obj.clone(), None).unwrap(); + + drop(ctx); + + // create a normal Context and make the 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_2( AsymmetricAlgorithmSelection::Rsa(RsaKeyBits::Rsa2048), None, ) @@ -753,7 +833,104 @@ 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( + let key_pub = + ek::create_ek_public_from_default_template(AsymmetricAlgorithm::Rsa, None).unwrap(); + let key_pub = if let Public::Rsa { + object_attributes, + name_hashing_algorithm, + auth_policy, + parameters, + .. + } = key_pub + { + Public::Rsa { + object_attributes, + name_hashing_algorithm, + auth_policy, + parameters, + unique: if let PublicKey::Rsa(val) = make_cred_params.attesting_key_pub { + PublicKeyRsa::try_from(val).unwrap() + } else { + panic!("Wrong public key type"); + }, + } + } else { + panic!("Wrong Public type"); + }; + let pub_handle = basic_ctx + .load_external_public(key_pub, Hierarchy::Owner) + .unwrap(); + + // Credential to expect back as proof for attestation + let credential = vec![0x53; 16]; + + let (cred, secret) = basic_ctx + .make_credential( + pub_handle, + credential.try_into().unwrap(), + make_cred_params.name.try_into().unwrap(), + ) + .unwrap(); + + drop(basic_ctx); + + // Create a new Transient key context and activate the credential + // Validation fails within the TPM because the credential HMAC is + // associated with a different object (so the integrity check fails). + let mut ctx = create_ctx(); + let e = ctx + .activate_credential( + wrong_obj, + None, + cred.value().to_vec(), + secret.value().to_vec(), + ) + .unwrap_err(); + if let Error::Tss2Error(e) = e { + assert_eq!(e.kind(), Some(Tss2ResponseCodeKind::Integrity)); + } else { + panic!("Got crate error ({}) when expecting an error from TPM.", e); + } +} + +#[test] +fn activate_credential_wrong_key_2() { + // create a Transient key context, generate two keys and + // obtain the Make Credential parameters for the first one + let mut ctx = create_ctx(); + let params = KeyParams::Ecc { + curve: EccCurve::NistP256, + scheme: EccScheme::create( + EccSchemeAlgorithm::EcDsa, + Some(HashingAlgorithm::Sha256), + None, + ) + .expect("Failed to create ecc scheme"), + }; + // "Good" key (for which the credential will be generated) + let (material, auth) = ctx.create_key(params, 16).unwrap(); + let obj = ObjectWrapper { + material, + params, + auth, + }; + let make_cred_params = ctx.get_make_cred_params(obj, None).unwrap(); + + // "Wrong" key (which will be used instead of the good key in attestation) + let (material, auth) = ctx.create_key(params, 16).unwrap(); + let wrong_obj = ObjectWrapper { + material, + params, + auth, + }; + + drop(ctx); + + // create a normal Context and make the 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_2( AsymmetricAlgorithmSelection::Rsa(RsaKeyBits::Rsa2048), None, )