Skip to main content

tss_esapi/context/tpm_commands/
non_volatile_storage.rs

1// Copyright 2021 Contributors to the Parsec project.
2// SPDX-License-Identifier: Apache-2.0
3use crate::{
4    context::handle_manager::HandleDropAction,
5    handles::{AuthHandle, NvIndexHandle, ObjectHandle},
6    interface_types::resource_handles::{NvAuth, Provision},
7    structures::{Auth, MaxNvBuffer, Name, NvPublic},
8    tss2_esys::{
9        Esys_NV_DefineSpace, Esys_NV_Increment, Esys_NV_Read, Esys_NV_ReadPublic,
10        Esys_NV_UndefineSpace, Esys_NV_Write,
11    },
12    Context, Error, Result,
13};
14use log::error;
15use std::convert::{TryFrom, TryInto};
16use std::ptr::null_mut;
17
18impl Context {
19    /// Allocates an index in the non volatile storage.
20    ///
21    /// # Details
22    /// This method will instruct the TPM to reserve space for an NV index
23    /// with the attributes defined in the provided parameters.
24    ///
25    /// # Arguments
26    /// * `nv_auth` - The [Provision] used for authorization.
27    /// * `auth` - The authorization value.
28    /// * `public_info` - The public parameters of the NV area.
29    pub fn nv_define_space(
30        &mut self,
31        nv_auth: Provision,
32        auth: Option<Auth>,
33        public_info: NvPublic,
34    ) -> Result<NvIndexHandle> {
35        let mut nv_handle = ObjectHandle::None.into();
36        let ret = unsafe {
37            Esys_NV_DefineSpace(
38                self.mut_context(),
39                AuthHandle::from(nv_auth).into(),
40                self.optional_session_1(),
41                self.optional_session_2(),
42                self.optional_session_3(),
43                &auth.unwrap_or_default().into(),
44                &public_info.try_into()?,
45                &mut nv_handle,
46            )
47        };
48        let ret = Error::from_tss_rc(ret);
49        if ret.is_success() {
50            self.handle_manager
51                .add_handle(nv_handle.into(), HandleDropAction::Close)?;
52            Ok(NvIndexHandle::from(nv_handle))
53        } else {
54            error!("Error when defining NV space: {}", ret);
55            Err(ret)
56        }
57    }
58
59    /// Deletes an index in the non volatile storage.
60    ///
61    /// # Details
62    /// The method will instruct the TPM to remove a
63    /// nv index.
64    ///
65    /// # Arguments
66    /// * `nv_auth` - The [Provision] used for authorization.
67    /// * `nv_index_handle`- The [NvIndexHandle] associated with
68    ///   the nv area that is to be removed.
69    pub fn nv_undefine_space(
70        &mut self,
71        nv_auth: Provision,
72        nv_index_handle: NvIndexHandle,
73    ) -> Result<()> {
74        let ret = unsafe {
75            Esys_NV_UndefineSpace(
76                self.mut_context(),
77                AuthHandle::from(nv_auth).into(),
78                nv_index_handle.into(),
79                self.optional_session_1(),
80                self.optional_session_2(),
81                self.optional_session_3(),
82            )
83        };
84
85        let ret = Error::from_tss_rc(ret);
86        if ret.is_success() {
87            self.handle_manager.set_as_closed(nv_index_handle.into())?;
88            Ok(())
89        } else {
90            error!("Error when undefining NV space: {}", ret);
91            Err(ret)
92        }
93    }
94
95    // Missing function: UndefineSpaceSpecial
96
97    /// Reads the public part of an nv index.
98    ///
99    /// # Details
100    /// This method is used to read the public
101    /// area and name of a nv index.
102    pub fn nv_read_public(&mut self, nv_index_handle: NvIndexHandle) -> Result<(NvPublic, Name)> {
103        let mut nv_public_ptr = null_mut();
104        let mut nv_name_ptr = null_mut();
105        let ret = unsafe {
106            Esys_NV_ReadPublic(
107                self.mut_context(),
108                nv_index_handle.into(),
109                self.optional_session_1(),
110                self.optional_session_2(),
111                self.optional_session_3(),
112                &mut nv_public_ptr,
113                &mut nv_name_ptr,
114            )
115        };
116        let ret = Error::from_tss_rc(ret);
117        if ret.is_success() {
118            Ok((
119                NvPublic::try_from(Context::ffi_data_to_owned(nv_public_ptr))?,
120                Name::try_from(Context::ffi_data_to_owned(nv_name_ptr))?,
121            ))
122        } else {
123            error!("Error when reading NV public: {}", ret);
124            Err(ret)
125        }
126    }
127
128    /// Writes data to an nv index.
129    ///
130    /// # Details
131    /// This method is used to write a value to
132    /// the nv memory in the TPM.
133    pub fn nv_write(
134        &mut self,
135        auth_handle: NvAuth,
136        nv_index_handle: NvIndexHandle,
137        data: MaxNvBuffer,
138        offset: u16,
139    ) -> Result<()> {
140        let ret = unsafe {
141            Esys_NV_Write(
142                self.mut_context(),
143                AuthHandle::from(auth_handle).into(),
144                nv_index_handle.into(),
145                self.optional_session_1(),
146                self.optional_session_2(),
147                self.optional_session_3(),
148                &data.into(),
149                offset,
150            )
151        };
152        let ret = Error::from_tss_rc(ret);
153        if ret.is_success() {
154            Ok(())
155        } else {
156            error!("Error when writing NV: {}", ret);
157            Err(ret)
158        }
159    }
160
161    /// Increment monotonic counter index
162    ///
163    /// # Details
164    /// This method is used to increment monotonic counter
165    /// in the TPM.
166    pub fn nv_increment(
167        &mut self,
168        auth_handle: NvAuth,
169        nv_index_handle: NvIndexHandle,
170    ) -> Result<()> {
171        let ret = unsafe {
172            Esys_NV_Increment(
173                self.mut_context(),
174                AuthHandle::from(auth_handle).into(),
175                nv_index_handle.into(),
176                self.optional_session_1(),
177                self.optional_session_2(),
178                self.optional_session_3(),
179            )
180        };
181        let ret = Error::from_tss_rc(ret);
182        if ret.is_success() {
183            Ok(())
184        } else {
185            error!("Error when incrementing NV: {}", ret);
186            Err(ret)
187        }
188    }
189
190    // Missing function: NV_Extend
191    // Missing function: NV_SetBits
192    // Missing function: NV_WriteLock
193    // Missing function: NV_GlobalWriteLock
194
195    /// Reads data from the nv index.
196    ///
197    /// # Details
198    /// This method is used to read a value from an area in
199    /// NV memory of the TPM.
200    pub fn nv_read(
201        &mut self,
202        auth_handle: NvAuth,
203        nv_index_handle: NvIndexHandle,
204        size: u16,
205        offset: u16,
206    ) -> Result<MaxNvBuffer> {
207        let mut data_ptr = null_mut();
208        let ret = unsafe {
209            Esys_NV_Read(
210                self.mut_context(),
211                AuthHandle::from(auth_handle).into(),
212                nv_index_handle.into(),
213                self.optional_session_1(),
214                self.optional_session_2(),
215                self.optional_session_3(),
216                size,
217                offset,
218                &mut data_ptr,
219            )
220        };
221        let ret = Error::from_tss_rc(ret);
222        if ret.is_success() {
223            MaxNvBuffer::try_from(Context::ffi_data_to_owned(data_ptr))
224        } else {
225            error!("Error when reading NV: {}", ret);
226            Err(ret)
227        }
228    }
229
230    // Missing function: NV_ReadLock
231    // Missing function: NV_ChangeAuth
232    // Missing function: NV_Certify
233}