tss_esapi/context/tpm_commands/
hierarchy_commands.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, KeyHandle, ObjectHandle},
6    interface_types::{resource_handles::Hierarchy, YesNo},
7    structures::{
8        Auth, CreatePrimaryKeyResult, CreationData, CreationTicket, Data, Digest, PcrSelectionList,
9        Public, SensitiveData,
10    },
11    tss2_esys::{
12        Esys_Clear, Esys_ClearControl, Esys_CreatePrimary, Esys_HierarchyChangeAuth,
13        TPM2B_SENSITIVE_CREATE, TPMS_SENSITIVE_CREATE,
14    },
15    Context, Error, Result,
16};
17use log::error;
18use std::{
19    convert::{TryFrom, TryInto},
20    mem::size_of,
21    ptr::null_mut,
22};
23
24impl Context {
25    /// Create a primary key and return the handle.
26    ///
27    /// The authentication value, initial data, outside info and creation PCRs are passed as slices
28    /// which are then converted by the method into TSS native structures.
29    ///
30    /// # Errors
31    /// * if either of the slices is larger than the maximum size of the native objects, a
32    ///   `WrongParamSize` wrapper error is returned
33    // TODO: Fix when compacting the arguments into a struct
34    #[allow(clippy::too_many_arguments)]
35    pub fn create_primary(
36        &mut self,
37        primary_handle: Hierarchy,
38        public: Public,
39        auth_value: Option<Auth>,
40        initial_data: Option<SensitiveData>,
41        outside_info: Option<Data>,
42        creation_pcrs: Option<PcrSelectionList>,
43    ) -> Result<CreatePrimaryKeyResult> {
44        let sensitive_create = TPM2B_SENSITIVE_CREATE {
45            size: size_of::<TPMS_SENSITIVE_CREATE>().try_into().unwrap(),
46            sensitive: TPMS_SENSITIVE_CREATE {
47                userAuth: auth_value.unwrap_or_default().into(),
48                data: initial_data.unwrap_or_default().into(),
49            },
50        };
51        let creation_pcrs = PcrSelectionList::list_from_option(creation_pcrs);
52
53        let mut out_public_ptr = null_mut();
54        let mut creation_data_ptr = null_mut();
55        let mut creation_hash_ptr = null_mut();
56        let mut creation_ticket_ptr = null_mut();
57        let mut object_handle = ObjectHandle::None.into();
58
59        let ret = unsafe {
60            Esys_CreatePrimary(
61                self.mut_context(),
62                ObjectHandle::from(primary_handle).into(),
63                self.optional_session_1(),
64                self.optional_session_2(),
65                self.optional_session_3(),
66                &sensitive_create,
67                &public.try_into()?,
68                &outside_info.unwrap_or_default().into(),
69                &creation_pcrs.into(),
70                &mut object_handle,
71                &mut out_public_ptr,
72                &mut creation_data_ptr,
73                &mut creation_hash_ptr,
74                &mut creation_ticket_ptr,
75            )
76        };
77        let ret = Error::from_tss_rc(ret);
78
79        if ret.is_success() {
80            let out_public_owned = Context::ffi_data_to_owned(out_public_ptr);
81            let creation_data_owned = Context::ffi_data_to_owned(creation_data_ptr);
82            let creation_hash_owned = Context::ffi_data_to_owned(creation_hash_ptr);
83            let creation_ticket_owned = Context::ffi_data_to_owned(creation_ticket_ptr);
84            let primary_key_handle = KeyHandle::from(object_handle);
85            self.handle_manager
86                .add_handle(primary_key_handle.into(), HandleDropAction::Flush)?;
87
88            Ok(CreatePrimaryKeyResult {
89                key_handle: primary_key_handle,
90                out_public: Public::try_from(out_public_owned)?,
91                creation_data: CreationData::try_from(creation_data_owned)?,
92                creation_hash: Digest::try_from(creation_hash_owned)?,
93                creation_ticket: CreationTicket::try_from(creation_ticket_owned)?,
94            })
95        } else {
96            error!("Error in creating primary key: {}", ret);
97            Err(ret)
98        }
99    }
100
101    // Missing function: HierarchyControl
102    // Missing function: SetPrimaryPolicy
103    // Missing function: ChangePPS
104    // Missing function: ChangeEPS
105
106    /// Clear all TPM context associated with a specific Owner
107    pub fn clear(&mut self, auth_handle: AuthHandle) -> Result<()> {
108        let ret = unsafe {
109            Esys_Clear(
110                self.mut_context(),
111                auth_handle.into(),
112                self.required_session_1()?,
113                self.optional_session_2(),
114                self.optional_session_3(),
115            )
116        };
117        let ret = Error::from_tss_rc(ret);
118
119        if ret.is_success() {
120            Ok(())
121        } else {
122            error!("Error in clearing TPM hierarchy: {}", ret);
123            Err(ret)
124        }
125    }
126
127    /// Disable or enable the TPM2_CLEAR command
128    pub fn clear_control(&mut self, auth_handle: AuthHandle, disable: bool) -> Result<()> {
129        let ret = unsafe {
130            Esys_ClearControl(
131                self.mut_context(),
132                auth_handle.into(),
133                self.required_session_1()?,
134                self.optional_session_2(),
135                self.optional_session_3(),
136                YesNo::from(disable).into(),
137            )
138        };
139        let ret = Error::from_tss_rc(ret);
140
141        if ret.is_success() {
142            Ok(())
143        } else {
144            error!("Error in controlling clear command: {}", ret);
145            Err(ret)
146        }
147    }
148
149    /// Change authorization for a hierarchy root
150    pub fn hierarchy_change_auth(&mut self, auth_handle: AuthHandle, new_auth: Auth) -> Result<()> {
151        let ret = unsafe {
152            Esys_HierarchyChangeAuth(
153                self.mut_context(),
154                auth_handle.into(),
155                self.required_session_1()?,
156                self.optional_session_2(),
157                self.optional_session_3(),
158                &new_auth.into(),
159            )
160        };
161        let ret = Error::from_tss_rc(ret);
162        if ret.is_success() {
163            Ok(())
164        } else {
165            error!("Error changing hierarchy auth: {}", ret);
166            Err(ret)
167        }
168    }
169}