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