From f7abb3d56c81ddb2f483004bfe72be0d04dac341 Mon Sep 17 00:00:00 2001 From: Michal Strug Date: Fri, 12 Dec 2025 18:43:03 +0100 Subject: [PATCH 1/8] Added hash_sequence_start() function Signed-off-by: Michal Strug --- .../tpm_commands/hash_hmac_event_sequences.rs | 36 +++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/tss-esapi/src/context/tpm_commands/hash_hmac_event_sequences.rs b/tss-esapi/src/context/tpm_commands/hash_hmac_event_sequences.rs index b80622d7f..5495e09ba 100644 --- a/tss-esapi/src/context/tpm_commands/hash_hmac_event_sequences.rs +++ b/tss-esapi/src/context/tpm_commands/hash_hmac_event_sequences.rs @@ -1,11 +1,43 @@ // Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 -use crate::Context; +use crate::{ + handles::ObjectHandle, interface_types::algorithm::HashingAlgorithm, structures::Auth, + tss2_esys::Esys_HashSequenceStart, Context, Result, ReturnCode, +}; +use log::error; impl Context { // Missing function: HMAC_Start // Missing function: MAC_Start - // Missing function: HashSequenceStart + + pub fn hash_sequence_start( + &mut self, + hashing_algorithm: HashingAlgorithm, + auth: Option, + ) -> Result { + let mut object_handle = ObjectHandle::None.into(); + ReturnCode::ensure_success( + unsafe { + Esys_HashSequenceStart( + self.mut_context(), + self.optional_session_1(), + self.optional_session_2(), + self.optional_session_3(), + &auth.unwrap_or_default().into(), + hashing_algorithm.into(), + &mut object_handle, + ) + }, + |ret| { + error!( + "Error failed to perform hash sequence start operation: {:#010X}", + ret + ); + }, + )?; + Ok(ObjectHandle::from(object_handle)) + } + // Missing function: SequenceUpdate // Missing function: SequenceComplete // Missing function: EventSequenceComplete From 295d64d6b63fdbb427864f382d3285baab3225e2 Mon Sep 17 00:00:00 2001 From: Michal Strug Date: Fri, 12 Dec 2025 19:18:08 +0100 Subject: [PATCH 2/8] Added sequence_update() function Signed-off-by: Michal Strug --- .../tpm_commands/hash_hmac_event_sequences.rs | 33 +++++++++++++++++-- 1 file changed, 30 insertions(+), 3 deletions(-) diff --git a/tss-esapi/src/context/tpm_commands/hash_hmac_event_sequences.rs b/tss-esapi/src/context/tpm_commands/hash_hmac_event_sequences.rs index 5495e09ba..adafa1824 100644 --- a/tss-esapi/src/context/tpm_commands/hash_hmac_event_sequences.rs +++ b/tss-esapi/src/context/tpm_commands/hash_hmac_event_sequences.rs @@ -1,8 +1,11 @@ // Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{ - handles::ObjectHandle, interface_types::algorithm::HashingAlgorithm, structures::Auth, - tss2_esys::Esys_HashSequenceStart, Context, Result, ReturnCode, + handles::ObjectHandle, + interface_types::algorithm::HashingAlgorithm, + structures::{Auth, MaxBuffer}, + tss2_esys::{Esys_HashSequenceStart, Esys_SequenceUpdate}, + Context, Result, ReturnCode, }; use log::error; @@ -38,7 +41,31 @@ impl Context { Ok(ObjectHandle::from(object_handle)) } - // Missing function: SequenceUpdate + pub fn sequence_update( + &mut self, + sequence_handle: ObjectHandle, + data: MaxBuffer, + ) -> Result<()> { + ReturnCode::ensure_success( + unsafe { + Esys_SequenceUpdate( + self.mut_context(), + sequence_handle.into(), + self.optional_session_1(), + self.optional_session_2(), + self.optional_session_3(), + &data.into(), + ) + }, + |ret| { + error!( + "Error failed to perform sequence update operation: {:#010X}", + ret + ); + }, + ) + } + // Missing function: SequenceComplete // Missing function: EventSequenceComplete } From a9287a8eec290e72972a113ec3b4715782e33619 Mon Sep 17 00:00:00 2001 From: Michal Strug Date: Fri, 12 Dec 2025 19:25:01 +0100 Subject: [PATCH 3/8] Added sequence_complete() function Signed-off-by: Michal Strug --- .../tpm_commands/hash_hmac_event_sequences.rs | 55 ++++++++++++++++--- 1 file changed, 47 insertions(+), 8 deletions(-) diff --git a/tss-esapi/src/context/tpm_commands/hash_hmac_event_sequences.rs b/tss-esapi/src/context/tpm_commands/hash_hmac_event_sequences.rs index adafa1824..d51e543d6 100644 --- a/tss-esapi/src/context/tpm_commands/hash_hmac_event_sequences.rs +++ b/tss-esapi/src/context/tpm_commands/hash_hmac_event_sequences.rs @@ -1,13 +1,14 @@ // Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 use crate::{ - handles::ObjectHandle, - interface_types::algorithm::HashingAlgorithm, - structures::{Auth, MaxBuffer}, - tss2_esys::{Esys_HashSequenceStart, Esys_SequenceUpdate}, + handles::{ObjectHandle, TpmHandle}, + interface_types::{algorithm::HashingAlgorithm, reserved_handles::Hierarchy}, + structures::{Auth, Digest, HashcheckTicket, MaxBuffer}, + tss2_esys::{Esys_HashSequenceStart, Esys_SequenceComplete, Esys_SequenceUpdate}, Context, Result, ReturnCode, }; use log::error; +use std::ptr::null_mut; impl Context { // Missing function: HMAC_Start @@ -18,7 +19,7 @@ impl Context { hashing_algorithm: HashingAlgorithm, auth: Option, ) -> Result { - let mut object_handle = ObjectHandle::None.into(); + let mut sequence_handle = ObjectHandle::None.into(); ReturnCode::ensure_success( unsafe { Esys_HashSequenceStart( @@ -28,7 +29,7 @@ impl Context { self.optional_session_3(), &auth.unwrap_or_default().into(), hashing_algorithm.into(), - &mut object_handle, + &mut sequence_handle, ) }, |ret| { @@ -38,7 +39,7 @@ impl Context { ); }, )?; - Ok(ObjectHandle::from(object_handle)) + Ok(ObjectHandle::from(sequence_handle)) } pub fn sequence_update( @@ -66,6 +67,44 @@ impl Context { ) } - // Missing function: SequenceComplete + pub fn sequence_complete( + &mut self, + sequence_handle: ObjectHandle, + data: MaxBuffer, + hierarchy: Hierarchy, + ) -> Result<(Digest, HashcheckTicket)> { + let mut out_hash_ptr = null_mut(); + let mut validation_ptr = null_mut(); + ReturnCode::ensure_success( + unsafe { + Esys_SequenceComplete( + self.mut_context(), + sequence_handle.into(), + self.optional_session_1(), + self.optional_session_2(), + self.optional_session_3(), + &data.into(), + if cfg!(hierarchy_is_esys_tr) { + ObjectHandle::from(hierarchy).into() + } else { + TpmHandle::from(hierarchy).into() + }, + &mut out_hash_ptr, + &mut validation_ptr, + ) + }, + |ret| { + error!( + "Error failed to perform sequence complete operation: {:#010X}", + ret + ); + }, + )?; + Ok(( + Digest::try_from(Context::ffi_data_to_owned(out_hash_ptr)?)?, + HashcheckTicket::try_from(Context::ffi_data_to_owned(validation_ptr)?)?, + )) + } + // Missing function: EventSequenceComplete } From 091128673a149324ece95e6cf468dfd0cab5e351 Mon Sep 17 00:00:00 2001 From: Michal Strug Date: Fri, 12 Dec 2025 19:37:05 +0100 Subject: [PATCH 4/8] Added hmac_sequence_start() function Signed-off-by: Michal Strug --- .../tpm_commands/hash_hmac_event_sequences.rs | 46 +++++++++++++++++-- 1 file changed, 42 insertions(+), 4 deletions(-) diff --git a/tss-esapi/src/context/tpm_commands/hash_hmac_event_sequences.rs b/tss-esapi/src/context/tpm_commands/hash_hmac_event_sequences.rs index d51e543d6..44d61bde2 100644 --- a/tss-esapi/src/context/tpm_commands/hash_hmac_event_sequences.rs +++ b/tss-esapi/src/context/tpm_commands/hash_hmac_event_sequences.rs @@ -4,14 +4,45 @@ use crate::{ handles::{ObjectHandle, TpmHandle}, interface_types::{algorithm::HashingAlgorithm, reserved_handles::Hierarchy}, structures::{Auth, Digest, HashcheckTicket, MaxBuffer}, - tss2_esys::{Esys_HashSequenceStart, Esys_SequenceComplete, Esys_SequenceUpdate}, + tss2_esys::{ + Esys_HMAC_Start, Esys_HashSequenceStart, Esys_SequenceComplete, Esys_SequenceUpdate, + }, Context, Result, ReturnCode, }; use log::error; use std::ptr::null_mut; impl Context { - // Missing function: HMAC_Start + pub fn hmac_sequence_start( + &mut self, + handle: ObjectHandle, + hashing_algorithm: HashingAlgorithm, + auth: Option, + ) -> Result { + let mut sequence_handle = ObjectHandle::None.into(); + ReturnCode::ensure_success( + unsafe { + Esys_HMAC_Start( + self.mut_context(), + handle.into(), + self.optional_session_1(), + self.optional_session_2(), + self.optional_session_3(), + &auth.unwrap_or_default().into(), + hashing_algorithm.into(), + &mut sequence_handle, + ) + }, + |ret| { + error!( + "Error failed to perform HMAC sequence start operation: {:#010X}", + ret + ); + }, + )?; + Ok(ObjectHandle::from(sequence_handle)) + } + // Missing function: MAC_Start pub fn hash_sequence_start( @@ -72,7 +103,7 @@ impl Context { sequence_handle: ObjectHandle, data: MaxBuffer, hierarchy: Hierarchy, - ) -> Result<(Digest, HashcheckTicket)> { + ) -> Result<(Digest, Option)> { let mut out_hash_ptr = null_mut(); let mut validation_ptr = null_mut(); ReturnCode::ensure_success( @@ -102,7 +133,14 @@ impl Context { )?; Ok(( Digest::try_from(Context::ffi_data_to_owned(out_hash_ptr)?)?, - HashcheckTicket::try_from(Context::ffi_data_to_owned(validation_ptr)?)?, + if validation_ptr.is_null() { + // For HMAC sequence validation parameter is NULL + None + } else { + Some(HashcheckTicket::try_from(Context::ffi_data_to_owned( + validation_ptr, + )?)?) + }, )) } From 85e5bf21582898e9bf22531a0779eae7deec50a6 Mon Sep 17 00:00:00 2001 From: Michal Strug Date: Mon, 15 Dec 2025 11:40:11 +0100 Subject: [PATCH 5/8] Added tests Signed-off-by: Michal Strug --- .../hash_hmac_event_sequences_tests.rs | 166 ++++++++++++++++++ 1 file changed, 166 insertions(+) diff --git a/tss-esapi/tests/integration_tests/context_tests/tpm_commands/hash_hmac_event_sequences_tests.rs b/tss-esapi/tests/integration_tests/context_tests/tpm_commands/hash_hmac_event_sequences_tests.rs index 72d8d89c5..540abaf8d 100644 --- a/tss-esapi/tests/integration_tests/context_tests/tpm_commands/hash_hmac_event_sequences_tests.rs +++ b/tss-esapi/tests/integration_tests/context_tests/tpm_commands/hash_hmac_event_sequences_tests.rs @@ -1,2 +1,168 @@ // Copyright 2021 Contributors to the Parsec project. // SPDX-License-Identifier: Apache-2.0 + +mod test_hash_sequence { + use crate::common::create_ctx_without_session; + use std::convert::TryFrom; + use tss_esapi::{ + interface_types::{algorithm::HashingAlgorithm, reserved_handles::Hierarchy}, + structures::{MaxBuffer, Ticket}, + }; + + #[test] + fn test_hash_sequence_with_sha_256() { + let mut context = create_ctx_without_session(); + + let data = "There is no spoon"; + let expected_hashed_data: [u8; 32] = [ + 0x6b, 0x38, 0x4d, 0x2b, 0xfb, 0x0e, 0x0d, 0xfb, 0x64, 0x89, 0xdb, 0xf4, 0xf8, 0xe9, + 0xe5, 0x2f, 0x71, 0xee, 0xb1, 0x0d, 0x06, 0x4c, 0x56, 0x59, 0x70, 0xcd, 0xd9, 0x44, + 0x43, 0x18, 0x5d, 0xc1, + ]; + let expected_hierarchy = Hierarchy::Owner; + let expected_ticked_digest: [u8; 48] = [ + 165, 70, 22, 78, 34, 29, 93, 104, 157, 3, 194, 141, 227, 62, 13, 113, 162, 117, 215, + 39, 206, 120, 56, 72, 177, 187, 242, 200, 129, 64, 216, 112, 77, 78, 135, 192, 40, 171, + 168, 40, 57, 132, 12, 101, 84, 148, 55, 125, + ]; + + let handle = context + .hash_sequence_start(HashingAlgorithm::Sha256, None) + .unwrap(); + context + .sequence_update( + handle, + MaxBuffer::try_from(data.as_bytes().to_vec()).unwrap(), + ) + .unwrap(); + let (actual_hashed_data, ticket) = context + .sequence_complete( + handle, + MaxBuffer::from_bytes(&[]).unwrap(), + expected_hierarchy, + ) + .unwrap(); + let ticket = ticket.unwrap(); + + assert_eq!(expected_hashed_data.len(), actual_hashed_data.len()); + assert_eq!(&expected_hashed_data[..], &actual_hashed_data[..]); + assert_eq!(ticket.hierarchy(), expected_hierarchy); + assert_eq!(ticket.digest().len(), expected_ticked_digest.len()); + assert_eq!(&ticket.digest()[..], &expected_ticked_digest[..]); + } + + #[test] + fn test_hash_sequence_long() { + let mut context = create_ctx_without_session(); + + let data = [0xEE; 5000]; + let expected_hashed_data: [u8; 32] = [ + 32, 190, 228, 96, 206, 94, 17, 15, 13, 7, 50, 27, 254, 139, 228, 145, 230, 210, 2, 119, + 69, 16, 252, 245, 236, 126, 214, 6, 171, 196, 33, 212, + ]; + let expected_hierarchy = Hierarchy::Owner; + let expected_ticked_digest: [u8; 48] = [ + 68, 142, 177, 202, 238, 232, 144, 173, 86, 148, 226, 71, 166, 84, 27, 61, 119, 133, + 122, 230, 74, 81, 149, 43, 193, 102, 99, 147, 2, 173, 120, 64, 69, 76, 62, 12, 231, 6, + 98, 78, 169, 120, 132, 199, 37, 190, 157, 156, + ]; + + let handle = context + .hash_sequence_start(HashingAlgorithm::Sha256, None) + .unwrap(); + + let chunks = data.chunks_exact(MaxBuffer::MAX_SIZE); + let last_chung = chunks.remainder(); + for chunk in chunks { + context + .sequence_update(handle, MaxBuffer::from_bytes(&chunk).unwrap()) + .unwrap(); + } + let (actual_hashed_data, ticket) = context + .sequence_complete( + handle, + MaxBuffer::from_bytes(&last_chung).unwrap(), + expected_hierarchy, + ) + .unwrap(); + let ticket = ticket.unwrap(); + + assert_eq!(expected_hashed_data.len(), actual_hashed_data.len()); + assert_eq!(&expected_hashed_data[..], &actual_hashed_data[..]); + assert_eq!(ticket.hierarchy(), expected_hierarchy); + assert_eq!(ticket.digest().len(), expected_ticked_digest.len()); + assert_eq!(&ticket.digest()[..], &expected_ticked_digest[..]); + } +} + +mod test_hmac_sequence { + use crate::common::create_ctx_without_session; + use tss_esapi::{ + attributes::ObjectAttributesBuilder, + interface_types::{ + algorithm::{HashingAlgorithm, PublicAlgorithm}, + reserved_handles::Hierarchy, + }, + structures::{ + KeyedHashScheme, MaxBuffer, PublicBuilder, PublicKeyedHashParameters, Ticket, + }, + }; + + #[test] + fn test_hmac() { + let mut context = create_ctx_without_session(); + + let object_attributes = ObjectAttributesBuilder::new() + .with_sign_encrypt(true) + .with_sensitive_data_origin(true) + .with_user_with_auth(true) + .build() + .expect("Failed to build object attributes"); + + let key_pub = PublicBuilder::new() + .with_public_algorithm(PublicAlgorithm::KeyedHash) + .with_name_hashing_algorithm(HashingAlgorithm::Sha256) + .with_object_attributes(object_attributes) + .with_keyed_hash_parameters(PublicKeyedHashParameters::new( + KeyedHashScheme::HMAC_SHA_256, + )) + .with_keyed_hash_unique_identifier(Default::default()) + .build() + .expect("Failed to build public structure for key."); + + let key = context + .create_primary(Hierarchy::Owner, key_pub, None, None, None, None) + .unwrap(); + + let data = [0xEE; 5000]; + let expected_hashed_data: [u8; 32] = [ + 164, 220, 137, 242, 158, 130, 178, 240, 189, 138, 102, 104, 4, 75, 1, 100, 220, 199, + 160, 230, 120, 187, 239, 105, 51, 26, 185, 205, 83, 208, 254, 252, + ]; + + let handle = context + .hmac_sequence_start(key.key_handle.into(), HashingAlgorithm::Sha256, None) + .unwrap(); + + let chunks = data.chunks_exact(MaxBuffer::MAX_SIZE); + let last_chunk = chunks.remainder(); + for chunk in chunks { + context + .sequence_update(handle, MaxBuffer::from_bytes(&chunk).unwrap()) + .unwrap(); + } + let (actual_hashed_data, ticket) = context + .sequence_complete( + handle, + MaxBuffer::from_bytes(&last_chunk).unwrap(), + Hierarchy::Null, + ) + .unwrap(); + let ticket = ticket.unwrap(); + + assert_eq!(expected_hashed_data.len(), actual_hashed_data.len()); + assert_eq!(&expected_hashed_data[..], &actual_hashed_data[..]); + assert_eq!(ticket.hierarchy(), Hierarchy::Null); + assert_eq!(ticket.digest().len(), 0); + } +} From 54d8a536f28342a36c4e30891bd604a3ef64be47 Mon Sep 17 00:00:00 2001 From: Michal Strug Date: Mon, 15 Dec 2025 18:54:49 +0100 Subject: [PATCH 6/8] Updated tests Signed-off-by: Michal Strug --- .../hash_hmac_event_sequences_tests.rs | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/tss-esapi/tests/integration_tests/context_tests/tpm_commands/hash_hmac_event_sequences_tests.rs b/tss-esapi/tests/integration_tests/context_tests/tpm_commands/hash_hmac_event_sequences_tests.rs index 540abaf8d..e71718bea 100644 --- a/tss-esapi/tests/integration_tests/context_tests/tpm_commands/hash_hmac_event_sequences_tests.rs +++ b/tss-esapi/tests/integration_tests/context_tests/tpm_commands/hash_hmac_event_sequences_tests.rs @@ -2,7 +2,7 @@ // SPDX-License-Identifier: Apache-2.0 mod test_hash_sequence { - use crate::common::create_ctx_without_session; + use crate::common::create_ctx_with_session; use std::convert::TryFrom; use tss_esapi::{ interface_types::{algorithm::HashingAlgorithm, reserved_handles::Hierarchy}, @@ -11,7 +11,7 @@ mod test_hash_sequence { #[test] fn test_hash_sequence_with_sha_256() { - let mut context = create_ctx_without_session(); + let mut context = create_ctx_with_session(); let data = "There is no spoon"; let expected_hashed_data: [u8; 32] = [ @@ -53,18 +53,15 @@ mod test_hash_sequence { #[test] fn test_hash_sequence_long() { - let mut context = create_ctx_without_session(); + let mut context = create_ctx_with_session(); - let data = [0xEE; 5000]; + let data = [0xEE; 2*1025]; let expected_hashed_data: [u8; 32] = [ - 32, 190, 228, 96, 206, 94, 17, 15, 13, 7, 50, 27, 254, 139, 228, 145, 230, 210, 2, 119, - 69, 16, 252, 245, 236, 126, 214, 6, 171, 196, 33, 212, + 85, 49, 213, 201, 29, 99, 203, 43, 17, 142, 166, 204, 103, 133, 234, 67, 160, 165, 94, 246, 210, 34, 63, 150, 131, 32, 20, 120, 122, 125, 176, 31 ]; let expected_hierarchy = Hierarchy::Owner; let expected_ticked_digest: [u8; 48] = [ - 68, 142, 177, 202, 238, 232, 144, 173, 86, 148, 226, 71, 166, 84, 27, 61, 119, 133, - 122, 230, 74, 81, 149, 43, 193, 102, 99, 147, 2, 173, 120, 64, 69, 76, 62, 12, 231, 6, - 98, 78, 169, 120, 132, 199, 37, 190, 157, 156, + 151, 194, 112, 114, 26, 225, 60, 219, 72, 28, 234, 75, 164, 187, 234, 94, 19, 63, 169, 135, 194, 112, 164, 79, 177, 81, 133, 176, 58, 208, 238, 57, 125, 238, 41, 120, 1, 94, 49, 40, 242, 35, 57, 69, 183, 61, 63, 101 ]; let handle = context @@ -96,7 +93,7 @@ mod test_hash_sequence { } mod test_hmac_sequence { - use crate::common::create_ctx_without_session; + use crate::common::create_ctx_with_session; use tss_esapi::{ attributes::ObjectAttributesBuilder, interface_types::{ @@ -110,7 +107,7 @@ mod test_hmac_sequence { #[test] fn test_hmac() { - let mut context = create_ctx_without_session(); + let mut context = create_ctx_with_session(); let object_attributes = ObjectAttributesBuilder::new() .with_sign_encrypt(true) From d215834ba1ca471073acf1ab17ca310c16dc603a Mon Sep 17 00:00:00 2001 From: Michal Strug Date: Mon, 15 Dec 2025 19:28:43 +0100 Subject: [PATCH 7/8] Added docs Signed-off-by: Michal Strug --- .../tpm_commands/hash_hmac_event_sequences.rs | 102 ++++++++++++++++++ 1 file changed, 102 insertions(+) diff --git a/tss-esapi/src/context/tpm_commands/hash_hmac_event_sequences.rs b/tss-esapi/src/context/tpm_commands/hash_hmac_event_sequences.rs index 44d61bde2..7d6e65ac3 100644 --- a/tss-esapi/src/context/tpm_commands/hash_hmac_event_sequences.rs +++ b/tss-esapi/src/context/tpm_commands/hash_hmac_event_sequences.rs @@ -13,6 +13,65 @@ use log::error; use std::ptr::null_mut; impl Context { + /// Starts HMAC sequence of large data (larger than MaxBuffer::MAX_SIZE) using the specified algorithm. + /// + /// # Details + /// When the amount of data to be included in a digest cannot be sent to the TPM in one atomic HMAC + /// command then a sequence of commands may be used to provide incremental updates to the digest. + /// Follow the pattern: + /// - Initialize sequence with `hmac_sequence_start()` + /// - Send data to calculate the hash with `sequence_update()` + /// - Finish hash calculation with call to `sequence_complete()` + /// + /// # Example + /// + /// ```rust + /// # Create context with session. + /// # let mut context = create_ctx_with_session(); + /// + /// let object_attributes = ObjectAttributesBuilder::new() + /// .with_sign_encrypt(true) + /// .with_sensitive_data_origin(true) + /// .with_user_with_auth(true) + /// .build() + /// .expect("Failed to build object attributes"); + /// + /// let key_pub = PublicBuilder::new() + /// .with_public_algorithm(PublicAlgorithm::KeyedHash) + /// .with_name_hashing_algorithm(HashingAlgorithm::Sha256) + /// .with_object_attributes(object_attributes) + /// .with_keyed_hash_parameters(PublicKeyedHashParameters::new( + /// KeyedHashScheme::HMAC_SHA_256, + /// )) + /// .with_keyed_hash_unique_identifier(Default::default()) + /// .build() + /// .expect("Failed to build public structure for key."); + /// + /// let key = context + /// .create_primary(Hierarchy::Owner, key_pub, None, None, None, None) + /// .unwrap(); + /// + /// let data = [0xEE; 5000]; + /// + /// let handle = context + /// .hmac_sequence_start(key.key_handle.into(), HashingAlgorithm::Sha256, None) + /// .unwrap(); + /// + /// let chunks = data.chunks_exact(MaxBuffer::MAX_SIZE); + /// let last_chunk = chunks.remainder(); + /// for chunk in chunks { + /// context + /// .sequence_update(handle, MaxBuffer::from_bytes(&chunk).unwrap()) + /// .unwrap(); + /// } + /// let (actual_hashed_data, ticket) = context + /// .sequence_complete( + /// handle, + /// MaxBuffer::from_bytes(&last_chunk).unwrap(), + /// Hierarchy::Null, + /// ) + /// .unwrap(); + /// ``` pub fn hmac_sequence_start( &mut self, handle: ObjectHandle, @@ -45,6 +104,43 @@ impl Context { // Missing function: MAC_Start + /// Starts hash sequence of large data (larger than MaxBuffer::MAX_SIZE) using the specified algorithm. + /// + /// # Details + /// When the amount of data to be included in a digest cannot be sent to the TPM in one atomic hash + /// command then a sequence of commands may be used to provide incremental updates to the digest. + /// Follow the pattern: + /// - Initialize sequence with `hash_sequence_start()` + /// - Send data to calculate the hash with `sequence_update()` + /// - Finish hash calculation with call to `sequence_complete()` + /// + /// # Example + /// + /// ```rust + /// # Create context with session. + /// # let mut context = create_ctx_with_session(); + /// + /// let data = [0xEE; 2*1025]; + /// + /// let handle = context + /// .hash_sequence_start(HashingAlgorithm::Sha256, None) + /// .unwrap(); + /// + /// let chunks = data.chunks_exact(MaxBuffer::MAX_SIZE); + /// let last_chung = chunks.remainder(); + /// for chunk in chunks { + /// context + /// .sequence_update(handle, MaxBuffer::from_bytes(&chunk).unwrap()) + /// .unwrap(); + /// } + /// let (actual_hashed_data, ticket) = context + /// .sequence_complete( + /// handle, + /// MaxBuffer::from_bytes(&last_chung).unwrap(), + /// expected_hierarchy, + /// ) + /// .unwrap(); + /// ``` pub fn hash_sequence_start( &mut self, hashing_algorithm: HashingAlgorithm, @@ -73,6 +169,9 @@ impl Context { Ok(ObjectHandle::from(sequence_handle)) } + /// Continues hash or HMAC sequence. + /// + /// @see hash_sequence_start(), hmac_sequence_start() pub fn sequence_update( &mut self, sequence_handle: ObjectHandle, @@ -98,6 +197,9 @@ impl Context { ) } + /// Finishes hash or HMAC sequence. + /// + /// @see hash_sequence_start(), hmac_sequence_start() pub fn sequence_complete( &mut self, sequence_handle: ObjectHandle, From 2f75eba7083ef6c150b56a350b3782baf94abbf0 Mon Sep 17 00:00:00 2001 From: Michal Strug Date: Tue, 16 Dec 2025 16:54:57 +0100 Subject: [PATCH 8/8] Updated formatting Signed-off-by: Michal Strug --- .../tpm_commands/hash_hmac_event_sequences_tests.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tss-esapi/tests/integration_tests/context_tests/tpm_commands/hash_hmac_event_sequences_tests.rs b/tss-esapi/tests/integration_tests/context_tests/tpm_commands/hash_hmac_event_sequences_tests.rs index e71718bea..71eff0d25 100644 --- a/tss-esapi/tests/integration_tests/context_tests/tpm_commands/hash_hmac_event_sequences_tests.rs +++ b/tss-esapi/tests/integration_tests/context_tests/tpm_commands/hash_hmac_event_sequences_tests.rs @@ -55,13 +55,16 @@ mod test_hash_sequence { fn test_hash_sequence_long() { let mut context = create_ctx_with_session(); - let data = [0xEE; 2*1025]; + let data = [0xEE; 2 * 1025]; let expected_hashed_data: [u8; 32] = [ - 85, 49, 213, 201, 29, 99, 203, 43, 17, 142, 166, 204, 103, 133, 234, 67, 160, 165, 94, 246, 210, 34, 63, 150, 131, 32, 20, 120, 122, 125, 176, 31 + 85, 49, 213, 201, 29, 99, 203, 43, 17, 142, 166, 204, 103, 133, 234, 67, 160, 165, 94, + 246, 210, 34, 63, 150, 131, 32, 20, 120, 122, 125, 176, 31, ]; let expected_hierarchy = Hierarchy::Owner; let expected_ticked_digest: [u8; 48] = [ - 151, 194, 112, 114, 26, 225, 60, 219, 72, 28, 234, 75, 164, 187, 234, 94, 19, 63, 169, 135, 194, 112, 164, 79, 177, 81, 133, 176, 58, 208, 238, 57, 125, 238, 41, 120, 1, 94, 49, 40, 242, 35, 57, 69, 183, 61, 63, 101 + 151, 194, 112, 114, 26, 225, 60, 219, 72, 28, 234, 75, 164, 187, 234, 94, 19, 63, 169, + 135, 194, 112, 164, 79, 177, 81, 133, 176, 58, 208, 238, 57, 125, 238, 41, 120, 1, 94, + 49, 40, 242, 35, 57, 69, 183, 61, 63, 101, ]; let handle = context