@@ -6,7 +6,7 @@ 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 ,
9
+ Esys_NV_DefineSpace , Esys_NV_Extend , Esys_NV_Increment , Esys_NV_Read , Esys_NV_ReadPublic ,
10
10
Esys_NV_UndefineSpace , Esys_NV_UndefineSpaceSpecial , Esys_NV_Write ,
11
11
} ,
12
12
Context , Result , ReturnCode ,
@@ -698,7 +698,123 @@ impl Context {
698
698
)
699
699
}
700
700
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
+
702
818
// Missing function: NV_SetBits
703
819
// Missing function: NV_WriteLock
704
820
// Missing function: NV_GlobalWriteLock
0 commit comments