Skip to content

Commit fc3eba3

Browse files
author
Nathan Rossi
committed
Add definition for NV_Extend
Add a implementation for NV_Extend, which is used with a NV Index defined with the NvIndexType::Extend to provide a PCR equivalent that uses NV memory. The hashing algorithm used is defined by the index name algorithm. An example and test are included for this function, setting up the NV index with the required type and typical attributes and performing an extend of the index and confirming the resulting hash value. Signed-off-by: Nathan Rossi <[email protected]>
1 parent a33e447 commit fc3eba3

File tree

1 file changed

+118
-2
lines changed

1 file changed

+118
-2
lines changed

tss-esapi/src/context/tpm_commands/non_volatile_storage.rs

Lines changed: 118 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ use crate::{
66
interface_types::reserved_handles::{NvAuth, Provision},
77
structures::{Auth, MaxNvBuffer, Name, NvPublic},
88
tss2_esys::{
9-
Esys_NV_DefineSpace, Esys_NV_Increment, Esys_NV_Read, Esys_NV_ReadPublic,
9+
Esys_NV_DefineSpace, Esys_NV_Extend, Esys_NV_Increment, Esys_NV_Read, Esys_NV_ReadPublic,
1010
Esys_NV_UndefineSpace, Esys_NV_UndefineSpaceSpecial, Esys_NV_Write,
1111
},
1212
Context, Result, ReturnCode,
@@ -698,7 +698,123 @@ impl Context {
698698
)
699699
}
700700

701-
// Missing function: NV_Extend
701+
/// Extends data to the NV memory associated with a nv index.
702+
///
703+
/// # Details
704+
/// This method is used to extend a value to
705+
/// the nv memory in the TPM.
706+
///
707+
/// Please beware that this method requires an authorization
708+
/// session handle to be present.
709+
///
710+
/// # Arguments
711+
/// * `auth_handle` - Handle indicating the source of authorization value.
712+
/// * `nv_index_handle` - The [NvIndexHandle] associated with NV memory
713+
/// which will be extended by data hashed with the previous data.
714+
/// * `data` - The data, in the form of a [MaxNvBuffer], that is to be written.
715+
///
716+
/// # Example
717+
/// ```rust
718+
/// # use tss_esapi::{
719+
/// # Context, TctiNameConf, attributes::{SessionAttributes, NvIndexAttributes},
720+
/// # handles::NvIndexTpmHandle, interface_types::algorithm::HashingAlgorithm,
721+
/// # structures::{SymmetricDefinition, NvPublic},
722+
/// # constants::SessionType, constants::nv_index_type::NvIndexType,
723+
/// # };
724+
/// use tss_esapi::{
725+
/// interface_types::reserved_handles::{Provision, NvAuth}, structures::MaxNvBuffer,
726+
/// };
727+
///
728+
/// # // Create context
729+
/// # let mut context =
730+
/// # Context::new(
731+
/// # TctiNameConf::from_environment_variable().expect("Failed to get TCTI"),
732+
/// # ).expect("Failed to create Context");
733+
/// #
734+
/// # let session = context
735+
/// # .start_auth_session(
736+
/// # None,
737+
/// # None,
738+
/// # None,
739+
/// # SessionType::Hmac,
740+
/// # SymmetricDefinition::AES_256_CFB,
741+
/// # tss_esapi::interface_types::algorithm::HashingAlgorithm::Sha256,
742+
/// # )
743+
/// # .expect("Failed to create session")
744+
/// # .expect("Received invalid handle");
745+
/// # let (session_attributes, session_attributes_mask) = SessionAttributes::builder()
746+
/// # .with_decrypt(true)
747+
/// # .with_encrypt(true)
748+
/// # .build();
749+
/// # context.tr_sess_set_attributes(session, session_attributes, session_attributes_mask)
750+
/// # .expect("Failed to set attributes on session");
751+
/// # context.set_sessions((Some(session), None, None));
752+
/// #
753+
/// # let nv_index = NvIndexTpmHandle::new(0x01500028)
754+
/// # .expect("Failed to create NV index tpm handle");
755+
/// #
756+
/// // Create NV index attributes
757+
/// let owner_nv_index_attributes = NvIndexAttributes::builder()
758+
/// .with_owner_write(true)
759+
/// .with_owner_read(true)
760+
/// .with_orderly(true)
761+
/// .with_nv_index_type(NvIndexType::Extend)
762+
/// .build()
763+
/// .expect("Failed to create owner nv index attributes");
764+
///
765+
/// // Create owner nv public.
766+
/// let owner_nv_public = NvPublic::builder()
767+
/// .with_nv_index(nv_index)
768+
/// .with_index_name_algorithm(HashingAlgorithm::Sha256)
769+
/// .with_index_attributes(owner_nv_index_attributes)
770+
/// .with_data_area_size(32)
771+
/// .build()
772+
/// .expect("Failed to build NvPublic for owner");
773+
///
774+
/// let nv_index_handle = context
775+
/// .nv_define_space(Provision::Owner, None, owner_nv_public.clone())
776+
/// .expect("Call to nv_define_space failed");
777+
///
778+
/// let data = MaxNvBuffer::try_from(vec![0x0]).unwrap();
779+
/// let result = context.nv_extend(NvAuth::Owner, nv_index_handle, data);
780+
///
781+
/// # let nv_read_result = context
782+
/// # .nv_read(NvAuth::Owner, nv_index_handle, 32, 0);
783+
/// # let read_data = nv_read_result.expect("Call to nv_read failed");
784+
/// # // expected value is sha256([0; 32] + [0; 1])
785+
/// # assert_eq!([
786+
/// # 0x7f, 0x9c, 0x9e, 0x31, 0xac, 0x82, 0x56, 0xca,
787+
/// # 0x2f, 0x25, 0x85, 0x83, 0xdf, 0x26, 0x2d, 0xbc,
788+
/// # 0x7d, 0x6f, 0x68, 0xf2, 0xa0, 0x30, 0x43, 0xd5,
789+
/// # 0xc9, 0x9a, 0x4a, 0xe5, 0xa7, 0x39, 0x6c, 0xe9],
790+
/// # read_data.as_ref());
791+
/// #
792+
/// # context
793+
/// # .nv_undefine_space(Provision::Owner, nv_index_handle)
794+
/// # .expect("Call to nv_undefine_space failed");
795+
/// ```
796+
pub fn nv_extend(
797+
&mut self,
798+
auth_handle: NvAuth,
799+
nv_index_handle: NvIndexHandle,
800+
data: MaxNvBuffer,
801+
) -> Result<()> {
802+
ReturnCode::ensure_success(
803+
unsafe {
804+
Esys_NV_Extend(
805+
self.mut_context(),
806+
AuthHandle::from(auth_handle).into(),
807+
nv_index_handle.into(),
808+
self.required_session_1()?,
809+
self.optional_session_2(),
810+
self.optional_session_3(),
811+
&data.into(),
812+
)
813+
},
814+
|ret| error!("Error when extending NV: {:#010X}", ret),
815+
)
816+
}
817+
702818
// Missing function: NV_SetBits
703819
// Missing function: NV_WriteLock
704820
// Missing function: NV_GlobalWriteLock

0 commit comments

Comments
 (0)