@@ -6,8 +6,9 @@ use crate::{
6
6
interface_types:: reserved_handles:: { NvAuth , Provision } ,
7
7
structures:: { Auth , MaxNvBuffer , Name , NvPublic } ,
8
8
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 ,
11
12
} ,
12
13
Context , Result , ReturnCode ,
13
14
} ;
@@ -698,7 +699,123 @@ impl Context {
698
699
)
699
700
}
700
701
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
+
702
819
// Missing function: NV_SetBits
703
820
// Missing function: NV_WriteLock
704
821
// Missing function: NV_GlobalWriteLock
0 commit comments