From b0c4c20d77d79dc6668c221bbd2705eeec9ced8f Mon Sep 17 00:00:00 2001 From: Nils Bourcarde Date: Mon, 5 Aug 2024 15:29:42 +0200 Subject: [PATCH 1/2] Implement Esys_GetTime wrapper Signed-off-by: Nils Bourcarde Co-authored-by: Nils Bourcarde Co-authored-by: Ionut Mihalcea --- .../tpm_commands/attestation_commands.rs | 118 +++++++++++++++++- 1 file changed, 116 insertions(+), 2 deletions(-) diff --git a/tss-esapi/src/context/tpm_commands/attestation_commands.rs b/tss-esapi/src/context/tpm_commands/attestation_commands.rs index 5576d192..8479f8d3 100644 --- a/tss-esapi/src/context/tpm_commands/attestation_commands.rs +++ b/tss-esapi/src/context/tpm_commands/attestation_commands.rs @@ -3,7 +3,7 @@ use crate::{ handles::{KeyHandle, ObjectHandle}, structures::{Attest, AttestBuffer, Data, PcrSelectionList, Signature, SignatureScheme}, - tss2_esys::{Esys_Certify, Esys_Quote}, + tss2_esys::{Esys_Certify, Esys_GetTime, Esys_Quote}, Context, Error, Result, }; use log::error; @@ -197,8 +197,122 @@ impl Context { } } + /// Get the current time and clock from the TPM + /// + /// # Arguments + /// * `signing_key_handle` - Handle of the key used to sign the attestation buffer + /// * `qualifying_data` - Qualifying data + /// * `signing_scheme` - Signing scheme to use if the scheme for `signing_key_handle` is `Null`. + /// + /// The `signing_key_handle` must be usable for signing. + /// + /// If `signing_key_handle` has the Restricted attribute set to `true` then `signing_scheme` must be + /// [SignatureScheme::Null]. + /// + /// # Returns + /// The command returns a tuple consisting of: + /// * `attest_data` - TPM-generated attestation data. + /// * `signature` - Signature for the attestation data. + /// + /// # Errors + /// * if the qualifying data provided is too long, a `WrongParamSize` wrapper error will be returned + /// + /// # Examples + /// + /// ```rust + /// # use tss_esapi::{Context, TctiNameConf}; + /// # use std::convert::TryFrom; + /// # use tss_esapi::{ + /// # abstraction::cipher::Cipher, + /// # interface_types::{ + /// # algorithm::{HashingAlgorithm, RsaSchemeAlgorithm}, + /// # key_bits::RsaKeyBits, + /// # resource_handles::Hierarchy, + /// # }, + /// # structures::{ + /// # RsaExponent, RsaScheme, + /// # }, + /// # utils::{create_unrestricted_signing_rsa_public, create_restricted_decryption_rsa_public}, + /// # }; + /// use std::convert::TryInto; + /// use tss_esapi::{ + /// structures::{Data, SignatureScheme}, + /// interface_types::session_handles::AuthSession, + /// }; + /// # let mut context = + /// # Context::new( + /// # TctiNameConf::from_environment_variable().expect("Failed to get TCTI"), + /// # ).expect("Failed to create Context"); + /// let qualifying_data = vec![0xff; 16]; + /// # let signing_key_pub = create_unrestricted_signing_rsa_public( + /// # RsaScheme::create(RsaSchemeAlgorithm::RsaSsa, Some(HashingAlgorithm::Sha256)) + /// # .expect("Failed to create RSA scheme"), + /// # RsaKeyBits::Rsa2048, + /// # RsaExponent::default(), + /// # ) + /// # .expect("Failed to create an unrestricted signing rsa public structure"); + /// # let sign_key_handle = context + /// # .execute_with_nullauth_session(|ctx| { + /// # ctx.create_primary(Hierarchy::Owner, signing_key_pub, None, None, None, None) + /// # }) + /// # .unwrap() + /// # .key_handle; + /// let (attest, signature) = context + /// .execute_with_sessions( + /// ( + /// Some(AuthSession::Password), + /// Some(AuthSession::Password), + /// None, + /// ), + /// |ctx| { + /// ctx.get_time( + /// sign_key_handle, + /// Data::try_from(qualifying_data).unwrap(), + /// SignatureScheme::Null, + /// ) + /// }, + /// ) + /// .expect("Failed to get tpm time"); + /// ``` + pub fn get_time( + &mut self, + signing_key_handle: KeyHandle, + qualifying_data: Data, + signing_scheme: SignatureScheme, + ) -> Result<(Attest, Signature)> { + let mut timeinfo_ptr = null_mut(); + let mut signature_ptr = null_mut(); + let ret = unsafe { + Esys_GetTime( + self.mut_context(), + ObjectHandle::Endorsement.into(), + signing_key_handle.into(), + self.required_session_1()?, + self.required_session_2()?, + self.optional_session_3(), + &qualifying_data.into(), + &signing_scheme.into(), + &mut timeinfo_ptr, + &mut signature_ptr, + ) + }; + + let ret = Error::from_tss_rc(ret); + + if ret.is_success() { + let timeinfo = Context::ffi_data_to_owned(timeinfo_ptr); + let signature = Context::ffi_data_to_owned(signature_ptr); + Ok(( + Attest::try_from(AttestBuffer::try_from(timeinfo)?)?, + Signature::try_from(signature)?, + )) + } else { + error!("Error in Get Time: {}", ret); + Err(ret) + } + } + // Missing function: GetSessionAuditDigest // Missing function: GestCommandAuditDigest - // Missing function: GetTime // Missing function: CertifyX509 } From fb18a006c3a406636814cf48f338014cea9d4360 Mon Sep 17 00:00:00 2001 From: Maurice Blattmann Date: Thu, 17 Oct 2024 12:54:15 +0200 Subject: [PATCH 2/2] Added testing for get_time Signed-off-by: Maurice Blattmann --- .../attestation_commands_tests.rs | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/tss-esapi/tests/integration_tests/context_tests/tpm_commands/attestation_commands_tests.rs b/tss-esapi/tests/integration_tests/context_tests/tpm_commands/attestation_commands_tests.rs index 313f2bb8..358e2f52 100644 --- a/tss-esapi/tests/integration_tests/context_tests/tpm_commands/attestation_commands_tests.rs +++ b/tss-esapi/tests/integration_tests/context_tests/tpm_commands/attestation_commands_tests.rs @@ -65,6 +65,47 @@ mod test_quote { } } + #[test] + fn time() { + let mut context = create_ctx_with_session(); + // No qualifying data + let qualifying_data = vec![0xff; 16]; + + let key_handle = context + .create_primary(Hierarchy::Owner, signing_key_pub(), None, None, None, None) + .unwrap() + .key_handle; + let (attest, _signature) = context + .execute_with_sessions( + ( + Some(AuthSession::Password), + Some(AuthSession::Password), + None, + ), + |ctx| { + ctx.get_time( + key_handle, + Data::try_from(qualifying_data).unwrap(), + SignatureScheme::Null, + ) + }, + ) + .expect("Failed to get time"); + + assert_eq!( + AttestationType::Time, + attest.attestation_type(), + "Attestation type of the returned value is not indicating Time" + ); + + match attest.attested() { + AttestInfo::Time { info: _ } => {} + _ => { + panic!("Attested did not contain the expected variant.") + } + } + } + #[test] fn certify() { let mut context = create_ctx_with_session();